Merge branch 'pre-master' into bt_dev

This commit is contained in:
Brian Taylor 2022-12-19 10:50:45 -08:00
commit 82465bea5f
54 changed files with 331 additions and 578 deletions

View File

@ -1,453 +0,0 @@
***************************************************************************
* DISCLAIMER *
* *
* The admst code generators, part of adms and this document are released *
* under LGPL license terms. *
* *
* Copyright (C) 2006 Freescale Inc. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
***************************************************************************
WARNING!
The text in this document has been prepared in 2006 and is outdated. It is
provided here only for reference and may provide some (historical)
information.
Please refer to the ngspice adms web page at
http://ngspice.sourceforge.net/admshowto.html
for actual information on how to integrate Verilog A device models into
ngspice.
Holger Vogt, May 2013
INTRODUCTION
In this document we will provide a guideline on how to auto-generate the
ready-to compile C code for the ngspice API of a compact device model
defined in the Verilog-AMS language.
Condition:
To compile Verilog-AMS compact models into ngspice-ready C models with
admsXml a copy of the latest adms distribution is needed. You get it from
the adms Download page http://mot-adms.sourceforge.net as a source code
package. (Also use of cvs version is possible, but needs some more effort.)
Version:
This guideline has been tested on Windows-XP under cygwin using:
$ admsXml -v
[usage] <release name="admsXml" version="2.1.3" date="Feb 2 2006" time="19:01:39"/>
[info] elapsed time: 0
[info] admst iterations: 0 (0 freed)
Goal:
In this guideline we will add device model hicum0 to ngspice
using the Verilog-AMS source code available at:
http://www.iee.et.tu-dresden.de/~schroter/Hicum_PD/Hicumna/hicumL0V1p11.va
Limitations:
The adms ngspice interface supports a limited set of Verilog-AMS language
constructs. See the home page of adms (http://mot-adms.sourceforge.net/)
for more info.
Feel free to contribute to the adms ngspice interface so that more
constructs can be supported.
01- ngspice Files
Ngspice does not (yet) have support for loading models at run time, every
model must be included at compile time. Then, adding a new model into
ngspice is a process that cannot be completely automated. Some files need
to be edited by hand.
01.01 What ngspice need to know of a new model ?
First you have to assign your new model a "device type". As you probably
know, ngspice recognizes the type of a device by the first letter in
device's name in the netlists ("r" for resistors, "q" for BJT, "m" for
mosfets and so on). Then the first thing you have to find is the correct
type for your new device (let's call this device_type).
Since there can be more than one model for each device type, another
parameter you have to set is the device_level, which must be unique
for each device type.
Once you have found the (device_type, device_level) couple you have
identified the files you have to edit:
<ngspice-data-tree>/configure.ac
Here you have to add the entries in adms section for your new directory
and library.
<ngspice-data-tree>/src/spicelib/parser/inp2<device_type>.c
Substitute <device_type> with the letter corresponding to the
type of you new model. Here you have to add the interface code for your
new device. In the case of hicum (a BJT model and thus a "q" device type)
you have to edit inp2q.c
<ngspice-data-tree>/src/spicelib/parser/inpdomod.c
Here you have to add a switch for the level of your new device.
<ngspice-data-tree>/src/spicelib/devices/dev.c
Follow the structure of the files and add information on your new
model. In dev.c you have to adjust some macro.
See existing examples to make the modifications for your own implementation.
<ngspice-data-tree> is the path to the ngspice source installation.
For instance <ngspice-data-tree> can be /tools/ng-spice-rework-17
Please see appendix 01 about spice3-flavoured flags.
02- adms Files
List of files that adms needs to create the ready-to-compile C code:
<ngspice-data-tree>/src/spicelib/devices/adms/admst/ngspice*.xml
adms creates the ready-to-compile C code from a set of admst code
generators. admst is a subset of the XML language which has been created
specifically for the purpose of C code generation. The syntax of admst is
very close to the XSLT language (it includes some extensions.)
03- Create the data file structure
Create the following directories if they do not already exist:
-a <ngspice-data-tree>/src/spicelib/devices/adms/hicum0
-b <ngspice-data-tree>/src/spicelib/devices/adms/hicum0/admsva
There is no convention on the way to choice the last directory name in -a.
However in -b 'admsva' is mandatory.
04- Save the Verilog-AMS source code
Save the source code of hicum0 from
http://www.iee.et.tu-dresden.de/~schroter/Hicum_PD/Hicumna/hicumL0V1p11.va
to:
<ngspice-data-tree>/src/spicelib/devices/adms/hicum0/admsva/hic0_full.va
NOTE: the name of the Verilog-AMS file that contains the 'module' declaration
should match the name of the module in the file.
For instance in file hic0_full.va you will find the following declaration:
...
module hic0_full (c,b,e,s);
...
05- Create file 'Makefile.am'
In directory ..../hicum0 run the following command in order to create file 'Makefile.am':
$ admsXml admsva/hic0_full.va -Iadmsva -e ../admst/ngspiceMakefile.am.xml
[info] admsXml-2.1.3 Feb 2 2006 19:01:39
[warning] [admsva\hic0_full.va:30]: standard vams file created (not found in -I path) ... 'constants.h'
[warning] [admsva\hic0_full.va:31]: standard vams file created (not found in -I path) ... 'discipline.h'
[info] Makefile.am: file created
[info] elapsed time: 1.0624
[info] admst iterations: 185425 (185425 freed)
After this step file 'Makefile.am' is created:
$ head Makefile.am
##
## Interface:
## created by: admsXml-2.1.3 - Monday, 01/30/06
## Process this file with automake to produce Makefile.in
ADMSXMLINTERFACE:=../admst
adms:
admsXml.exe -Iadmsva admsva/hic0_full.va \
06- Update/Create the auto-tools files (configure, Makefile.in, Makefile)
06.01 Manual changes
In directory <ngspice-data-tree> edit file configure.ac, add new device 'hicum0'
(use the name of the directory - not the name of the module):
$ grep hicum0 configure.ac
src/spicelib/devices/adms/hicum0/Makefile \
In directory <ngspice-data-tree>/src/spicelib/devices edit file Makefile.am, add new device 'hicum0':
$ grep hicum0 Makefile.am
adms/hicum0 \
adms/hicum0 \
06.02 Makefile.in
In directory <ngspice-data-tree> run the shell command 'automake':
File 'Makefile.in' is created in directory <ngspice-data-tree>/src/spicelib/devices/hicum0.
In directory <ngspice-data-tree>/src/spicelib/devices/hicum0 you should have:
$ ls
Makefile.am Makefile.in admsva constants.h discipline.h
06.03 Update file 'configure'
In directory <ngspice-data-tree> run the shell command 'autoconf':
File 'configure' is updated.
Edit the file to make sure that "adms/hicum0/Makefile" is present in the file.
06.04 Makefile
In directory <ngspice-data-tree> run shell command 'configure':
$ configure
...
config.status: creating src/spicelib/devices/adms/hicum0/Makefile
...
File 'Makefile' is created in directory <ngspice-data-tree>/src/spicelib/devices/hicum0.
In directory <ngspice-data-tree>/src/spicelib/devices/hicum0 you should have:
$ ls
Makefile Makefile.am Makefile.in admsva constants.h discipline.h
07- Create the ready-to-compile auto-generated C code of device hicum0
In directory ..../hicum0 run the following command in order to create the auto-generated C code:
$ make adms
admsXml.exe -Iadmsva admsva/hic0_full.va \
-e ../admst/ngspiceVersion.xml \
-e ../admst/ngspiceMakefile.am.xml \
-e ../admst/ngspiceMODULEitf.h.xml \
-e ../admst/ngspiceMODULEinit.c.xml \
-e ../admst/ngspiceMODULEinit.h.xml \
-e ../admst/ngspiceMODULEext.h.xml \
-e ../admst/ngspiceMODULEdefs.h.xml \
-e ../admst/ngspiceMODULEask.c.xml \
-e ../admst/ngspiceMODULEmask.c.xml \
-e ../admst/ngspiceMODULEpar.c.xml \
-e ../admst/ngspiceMODULEmpar.c.xml \
-e ../admst/ngspiceMODULEload.c.xml \
-e ../admst/ngspiceMODULEacld.c.xml \
-e ../admst/ngspiceMODULEtemp.c.xml \
-e ../admst/ngspiceMODULEsetup.c.xml \
-e ../admst/ngspiceMODULEguesstopology.c.xml \
-e ../admst/ngspiceMODULE.c.xml
[info] admsXml-2.1.3 Feb 2 2006 19:01:39
[info] Makefile.am: file created
[info] hic0_fullitf.h: file created
[info] hic0_fullinit.c: file created
[info] hic0_fullinit.h: file created
[info] hic0_fullext.h: file created
[info] hic0_fulldefs.h: file created
[info] hic0_fullask.c: file created
[info] hic0_fullmask.c: file created
[info] hic0_fullpar.c: file created
[info] hic0_fullmpar.c: file created
[info] noise contribution not implemented - ignored!
[info] noise contribution not implemented - ignored!
[info] noise contribution not implemented - ignored!
[info] noise contribution not implemented - ignored!
[info] noise contribution not implemented - ignored!
[info] noise contribution not implemented - ignored!
[info] hic0_fullload.c: file created
[info] hic0_fullacld.c: file created
[info] hic0_fulltemp.c: file created
[info] hic0_fullsetup.c: file created
[info] hic0_fullguesstopology.c: file created
[info] hic0_full.c: file created
[info] elapsed time: 5.43757
[info] admst iterations: 1099640 (1099640 freed)
perl -p -i -e 's/IOP\("(\w+)"/IOP("\L\1"/' hic0_full.c
In directory <ngspice-data-tree>/src/spicelib/devices/hicum0 you should have:
$ ls
Makefile constants.h hic0_fullacld.c hic0_fullguesstopology.c hic0_fullload.c hic0_fullsetup.c
Makefile.am discipline.h hic0_fullask.c hic0_fullinit.c hic0_fullmask.c hic0_fulltemp.c
Makefile.in hic0_full.c hic0_fulldefs.h hic0_fullinit.h hic0_fullmpar.c
admsva hic0_fullext.h hic0_fullitf.h hic0_fullpar.c
08- Compile the ready-to-compile auto-generated C code
In directory ..../hicum0 run the following command in order to create the object files*.o and libhic0_full.a:
$ make CFLAGS="-g"
if gcc -DHAVE_CONFIG_H -I. -I. -I../../../../.. -I../../../../../src/include -g -MT hic0_full.o
-MD -MP -MF ".ds/hic0_full.Tpo" -c -o hic0_full.o hic0_full.c; \
then mv -f ".deps/hic0_full.Tpo" ".deps/hic0_full.Po"; else rm -f ".deps/hic0_full.Tpo"; exit 1; fi
...
ar cru libhic0_full.a hic0_full.o hic0_fullacld.o hic0_fullask.o hic0_fullguesstopology.o hic0_fullinit.o
hic0_fullload.o hic0_fullmask.o hic0_fullmpar.o hic0_fullpar.o hic0_fullsetup.o hic0_fulltemp.o
ranlib libhic0_full.a
WARNING: at the compilation step some messages about '#warning conflict' will be printed.
They mean that some ngspice reserved keywords have been used in the Verilog-AMS.
Just ignore them in the case of hicum0.
In directory <ngspice-data-tree>/src/spicelib/devices/hicum0 you should have:
$ ls
Makefile hic0_full.c hic0_fullask.o hic0_fullinit.h hic0_fullmask.o hic0_fullsetup.o
Makefile.am hic0_fulldefs.h hic0_fullinit.o hic0_fullmpar.c hic0_fulltemp.c
Makefile.in hic0_full.o hic0_fullext.h hic0_fullitf.h hic0_fullmpar.o hic0_fulltemp.o
admsva hic0_fullacld.c hic0_fullguesstopology.c hic0_fullload.c hic0_fullpar.c libhic0_full.a
constants.h hic0_fullacld.o hic0_fullguesstopology.o hic0_fullload.o hic0_fullpar.o
discipline.h hic0_fullask.c hic0_fullinit.c hic0_fullmask.c hic0_fullsetup.c
NOTE: CFLAGS is redefined to "-g" is order to speed up the compilation process.
It is better NOT to redefine CFLAGS for official releases.
(the compilation will take a lot longer to complete)
09- Update manually the ngspice parser files
Modify the following files:
<ngspice-data-tree>/src/spicelib/parser/inp2q.c ----> depends on the type of the device, here 'q' device
<ngspice-data-tree>/src/spicelib/parser/inpdomod.c
<ngspice-data-tree>/src/spicelib/devices/dev.c
...
10- Update executable 'ngspice'
10-01 Update ngspice
In directory <ngspice-data-tree> run shell command 'make':
$ make
File 'src/ngspice.exe' is updated and contains the new device 'hicum0'.
10-02 Install ngspice
In directory <ngspice-data-tree> run shell command 'make':
$ make install
ngspice executables are installed in /usr/local/bin.
11- Test the Implementation of hicum0 into ngspice
11-01 Create a simple ngspice netlist
Create file 'hicum0.sp'. Its contents is given below:
$ cat hicum0.sp
.title Netlist
.option
+ temp=25.0
+ reltol=1e-5
+ abstol=1e-15
.model mybjtmodel npn
+ npn=1
+ level=5
qN1
+ c b 0 0
+ mybjtmodel
rcc cc c 100.0
rbb bb b 1k
vcc
+ cc 0
+ 1.0
vbb
+ bb 0
+ 0.0
+ ac=0.0
.dc vbb 0.0 1.0 0.02
.print
+ dc
+ v(c)
+ i(vbb)
+ i(vcc)
.end
11-02 run 'ngspice':
$ ngspice -b hicum0.sp
Circuit: .title Netlist
Doing analysis at TEMP = 298.150000 and TNOM = 300.150000
No. of Data Rows : 51
.title Netlist
DC transfer characteristic Mon Jan 30 10:22:01 2006
--------------------------------------------------------------------------------
Index v-sweep v(c) vbb#branch vcc#branch
--------------------------------------------------------------------------------
0 0.000000e+00 1.000000e+00 0.000000e+00 -7.105421e-17
1 2.000000e-02 1.000000e+00 -5.593842e-19 -1.265654e-16
2 4.000000e-02 1.000000e+00 -2.076336e-18 -2.775558e-16
3 6.000000e-02 1.000000e+00 -5.366258e-18 -6.061817e-16
4 8.000000e-02 1.000000e+00 -1.254873e-17 -1.320055e-15
5 1.000000e-01 1.000000e+00 -2.812744e-17 -2.874367e-15
6 1.200000e-01 1.000000e+00 -7.629085e-17 -7.666090e-15
7 1.400000e-01 1.000000e+00 -1.669761e-16 -1.669553e-14
8 1.600000e-01 1.000000e+00 -3.645759e-16 -3.636425e-14
9 1.800000e-01 1.000000e+00 -7.948513e-16 -7.920553e-14
10 2.000000e-01 1.000000e+00 -1.732082e-15 -1.725142e-13
11 2.200000e-01 1.000000e+00 -3.773484e-15 -3.757461e-13
12 2.400000e-01 1.000000e+00 -8.219658e-15 -8.183998e-13
13 2.600000e-01 1.000000e+00 -1.790375e-14 -1.782522e-12
14 2.800000e-01 1.000000e+00 -3.899630e-14 -3.882434e-12
15 3.000000e-01 1.000000e+00 -8.493698e-14 -8.456170e-12
16 3.200000e-01 1.000000e+00 -1.849987e-13 -1.841804e-11
17 3.400000e-01 1.000000e+00 -4.029389e-13 -4.011557e-11
18 3.600000e-01 1.000000e+00 -8.776254e-13 -8.737407e-11
19 3.800000e-01 1.000000e+00 -1.911521e-12 -1.903059e-10
20 4.000000e-01 1.000000e+00 -4.163405e-12 -4.144973e-10
21 4.200000e-01 9.999999e-01 -9.068141e-12 -9.027994e-10
22 4.400000e-01 9.999998e-01 -1.975094e-11 -1.966349e-09
23 4.600000e-01 9.999996e-01 -4.301867e-11 -4.282821e-09
24 4.800000e-01 9.999991e-01 -9.369701e-11 -9.328218e-09
25 5.000000e-01 9.999980e-01 -2.040767e-10 -2.031732e-08
26 5.200000e-01 9.999956e-01 -4.444870e-10 -4.425191e-08
27 5.400000e-01 9.999904e-01 -9.680991e-10 -9.638130e-08
28 5.600000e-01 9.999790e-01 -2.108483e-09 -2.099148e-07
29 5.800000e-01 9.999543e-01 -4.591957e-09 -4.571626e-07
30 6.000000e-01 9.999004e-01 -9.999448e-09 -9.955176e-07
31 6.200000e-01 9.997833e-01 -2.176941e-08 -2.167303e-06
32 6.400000e-01 9.995284e-01 -4.736784e-08 -4.715812e-06
33 6.600000e-01 9.989751e-01 -1.029470e-07 -1.024912e-05
34 6.800000e-01 9.977781e-01 -2.231776e-07 -2.221894e-05
35 7.000000e-01 9.952090e-01 -4.812339e-07 -4.791028e-05
36 7.200000e-01 9.897838e-01 -1.026165e-06 -1.021618e-04
37 7.400000e-01 9.786930e-01 -2.140206e-06 -2.130697e-04
38 7.600000e-01 9.573154e-01 -4.287705e-06 -4.268455e-04
39 7.800000e-01 9.197474e-01 -8.062749e-06 -8.025264e-04
40 8.000000e-01 8.611162e-01 -1.395965e-05 -1.388838e-03
41 8.200000e-01 7.801099e-01 -2.212604e-05 -2.198901e-03
42 8.400000e-01 6.791392e-01 -3.235919e-05 -3.208608e-03
43 8.600000e-01 5.627227e-01 -4.429334e-05 -4.372773e-03
44 8.800000e-01 4.367031e-01 -5.756142e-05 -5.632969e-03
45 9.000000e-01 3.111929e-01 -7.186079e-05 -6.888071e-03
46 9.200000e-01 2.120521e-01 -8.696058e-05 -7.879479e-03
47 9.400000e-01 1.637984e-01 -1.026891e-04 -8.362016e-03
48 9.600000e-01 1.443326e-01 -1.189191e-04 -8.556674e-03
49 9.800000e-01 1.353683e-01 -1.355550e-04 -8.646317e-03
50 1.000000e+00 1.312181e-01 -1.525242e-04 -8.687819e-03
Total elapsed time: 0.625 seconds.
Current dynamic memory usage = 1.515520 MB,
Dynamic memory limit = 1241.702400 MB.
12- How to update ngspice when the Verilog-AMS source code changes
If you modify the Verilog-AMS source code of 'hicum0'
just complete the following steps in order to update
'ngspice':
12-01 Update the auto-generated C code
In directory ..../hicum0 run:
- make clean
- make adms
- make
12-02 Update 'ngspice' and re-install
In directory <ngspice-data-tree> run:
- make
- make install
Appendix 01: Comments on spice3-flavoured flags like npn, pnp, nmos, pmos and so on
In the adms-based implementation of hicum0 the value of the device type flag (either npn or pnp)
in the model card is just ignored.
The selection of the type of the device is actually done using model parameters.
In the Verilog-AMS code of hicum0 there are two special model parameters called 'npn' and 'pnp'
which decide what the type of the device will be (either a npn bipolar model or pnp bipolar model).
The Verilog-AMS piece of code that triggers the decision is as follows:
if (`PGIVEN(npn))
HICUMtype = `NPN;
else if (`PGIVEN(pnp))
HICUMtype = `PNP;
else
HICUMtype = `NPN;
end
`PGIVEN(npn) is a macro that returns 1 is model parameter 'npn' occurs in the .model card
of the ngspice netlist. Otherwise it returns 0.
For instance:
1- the following model card will select a NPN type device:
.model mybjtmodel npn
+ npn=1
+ level=5
2- the following model card will select a PNP type device:
.model mybjtmodel npn
+ pnp=1
+ level=5
In both cases flag 'npn' is just ignored.
In section 'Update manually the ngspice parser files' it is recommended
to use flag 'adms' instead.
This limitation results from the LRM of VerilogAMS that does not support flags.

View File

@ -1,5 +1,12 @@
This document is covered by the Creative Commons Attribution Share-Alike (CC-BY-SA) v4.0. .
As of Jan. 23 ADMS is deprectated and replaced by OpenVAF/OSDI.
See README_OSDI.md and README_OSDI_howto.
All references to ADMS will be removed in a future ngspice release.
*************** Verilog A Device models in ngspice ******************************************

60
README_OSDI_howto Normal file
View File

@ -0,0 +1,60 @@
A 'quick and dirty' howto for OpenVAF and OSDI:
Example BSIMBULK
Tested under MS Windows 10 and OpenSUSE 15.4
Have OpenVAF compiler available.
Executables for download are available at https://openvaf.semimod.de/download/
for Linux and MS Windows.
Download BSIMBULK model from http://www.bsim.berkeley.edu/models/bsimbulk/
Open bsimbulk.va in a text editor
Search for the module name, here:
module bsimbulk(d, g, s, b, t);
The module name 'bsimbulk' will become the new model type in the .model statement
.model mname type ( pname1 = pval1 pname2 = pval2 ... ).
Compile bsimbulk.va with OpenVAF to obtain bsimbulk.osdi
Put bsimbulk.osdi into directory bsimbulk/test_osdi_libs
Search for suitable model parameters
BSIMBULK107 distro does not contain any parameters
BSIMBULK106 does contain a model parameter file model.l among the benchmark tests
Put model.l into directory bsimbulk/Modelcards
Edit model.l:
Check if model type is 'bsimbulk' (it is already)
Choose a model name for mname (nch or pch may be o.k., or BSIMBULK_osdi_N or ...)
There are NMOS and PMOS parameters in the same file here.
Create a ngspice netlist in directory bsimbulk, e.g. bb_IDvsVG.cir.
*** BSIMBULK107 Id versus Vgs ***
* the voltage sources
Vd dd 0 50m
Vg gg 0 1
Vs ss 0 0
Vb bb 0 0
* load the model parameter sets
.include Modelcards/model.l
* the call to the transistor (OSDI devices always start with N !)
NMN1 dd gg ss bb BSIMBULK_osdi_N W=500n L=90n
* the .control section
.control
* load the model dynamically
pre_osdi test_osdi_libs/bsimbulk.osdi
* the dc simulation
dc Vg 0 1.5 0.01 Vb 0 -1.6 -0.4
* plotting
set xbrushwidth=3
plot I(Vs)
.endc
.end
*********************************
So we have two OSDI specific actions in the netlist:
load the model by
pre_osdi test_osdi_libs/bsimbulk.osdi
instantiate the transistor by
NMN1 dd gg ss bb BSIMBULK_osdi_N W=500n L=90n

View File

@ -5,6 +5,6 @@
.include 74HCng_short_2.lib
.param vcc=3 tripdt=6n
.include adder_common.inc
.include ../adder_common.inc
.END

View File

@ -28,7 +28,7 @@ c2 z vss 0.576f
.dc V1 0 'vcc' 'vcc/100'
.control
pre_osdi test_osdi_win/ekv26_mod.osdi
pre_osdi osdi_libs/ekv26_mod.osdi
run
*set nolegend
set xbrushwidth=3

View File

@ -15,7 +15,7 @@ VB bb 0 0
N1 dd gg ss bb nch W=5e-6 L=0.5e-6
.control
pre_osdi test_osdi_win/ekv26_mod.osdi
pre_osdi osdi_libs/ekv26_mod.osdi
set xbrushwidth=3
* a DC sweep: drain, gate
dc Vd 0 1.6 0.01 VG 0 1.6 0.2

View File

@ -15,7 +15,7 @@ VB bb 0 0
N1 dd gg ss bb pch W=5e-6 L=5e-7
.control
pre_osdi test_osdi_win/ekv26_mod.osdi
pre_osdi osdi_libs/ekv26_mod.osdi
set xbrushwidth=3
* a DC sweep: drain, gate
*op

View File

@ -1,10 +1,11 @@
A 'quick and dirty' howto for OpenVAF and OSDI:
Example BSIMBULK
Tested under MS Windows 10
Tested under MS Windows 10 and OpenSUSE 15.4
Have OpenVAF compiler available.
Sources will be available soon.
Executables for download are available at https://openvaf.semimod.de/download/
for Linux and MS Windows.
Download BSIMBULK model from http://www.bsim.berkeley.edu/models/bsimbulk/
Open bsimbulk.va in a text editor
Search for the module name, here:
@ -12,7 +13,7 @@ Search for the module name, here:
The module name 'bsimbulk' will become the new model type in the .model statement
.model mname type ( pname1 = pval1 pname2 = pval2 ... ).
Compile bsimbulk.va with OpenVAF to obtain bsimbulk.osdi
Put bsimbulk.osdi into directory bsimbulk/test_osdi_win
Put bsimbulk.osdi into directory bsimbulk/osdi_libs
Search for suitable model parameters
BSIMBULK107 distro does not contain any parameters
BSIMBULK106 does contain a model parameter file model.l among the benchmark tests
@ -40,7 +41,7 @@ NMN1 dd gg ss bb BSIMBULK_osdi_N W=500n L=90n
* the .control section
.control
* load the model dynamically
pre_osdi test_osdi_win/bsimbulk107.osdi
pre_osdi osdi_libs/bsimbulk.osdi
* the dc simulation
dc Vg 0 1.5 0.01 Vb 0 -1.6 -0.4
* plotting
@ -52,7 +53,7 @@ plot I(Vs)
So we have two OSDI specific actions in the netlist:
load the model by
pre_osdi test_osdi_win/bsimbulk107.osdi
pre_osdi osdi_libs/bsimbulk.osdi
instantiate the transistor by
NMN1 dd gg ss bb BSIMBULK_osdi_N W=500n L=90n

View File

@ -27,7 +27,7 @@ c2 z vss 0.576f
.dc V1 0 'vcc' 'vcc/100'
.control
pre_osdi test_osdi_win/bsimbulk107.osdi
pre_osdi osdi_libs/bsimbulk107.osdi
run
*set nolegend
set xbrushwidth=3

View File

@ -31,7 +31,7 @@ c2 z vss 0.576f
.tran 10p 10n uic
.control
pre_osdi test_osdi_win/bsimbulk107.osdi
pre_osdi osdi_libs/bsimbulk107.osdi
run
set xbrushwidth=3
plot in

View File

@ -89225,7 +89225,7 @@ c2 z vss 0.834f
*.print tran V(g7529_1) V(g7509_0) V(g7484_1) V(g7477_1) V(g7460_0) V(g7503_1) V(g7522_0) V(g7485_1) V(g7453_0) V(g7474_0) V(g7500_0) V(g7514_0) V(g7546_1) V(g7549_0) V(g7467_0) V(g7491_0) V(g7456_0) V(g7495_1) V(g7545_0) V(g7473_0) V(g7541_0) V(g7448_1) V(g7525_1) V(g7550_1) V(g165_1) V(g7510_1) V(g7535_1) V(g7534_1) V(g7469_1) V(g7476_0) V(g7517_1) V(g7537_0) V(g7489_1) V(g7521_1) V(g7486_0) V(g7533_1) V(g7449_0) V(g7447_0) V(g7528_0) V(g7513_1) V(g7548_0) V(g7544_1) V(g7552_0) V(g7540_1) V(g7507_0) V(g7481_0) V(g7455_0) V(g7502_1) V(g7446_1) V(g7478_1) V(g7470_0) V(g7526_0) V(g7494_1) V(g7452_1) V(g7463_0) V(g7532_1) V(g7512_0) V(g7527_0) V(g7451_0) V(g7472_0) V(g7498_1) V(g7475_0) V(g7536_0) V(g7488_1) V(g7493_1) V(g7551_1) V(g7482_0) V(g7487_1) V(g7501_1) V(g7520_1) V(g7516_1) V(g7450_1) V(g7508_0) V(g7458_1) V(g7479_1) V(g7506_1) V(g7499_0) V(g7471_0) V(g7465_1) V(g7464_1) V(g7543_1) V(g7524_0) V(g7539_1) V(g7468_1) V(g7459_0) V(g7504_1) V(g7515_1) V(g7492_1) V(g7511_0) V(g7462_1) V(g7530_0) V(g7497_1) V(g7454_1) V(g7519_1) V(g7531_0) V(g7547_0) V(g7483_1) V(g7466_1) V(g7480_1) V(g7523_1) V(g7496_0) V(g7538_0) V(g7490_1) V(g7518_1) V(g7461_0) V(g7542_0) V(g7457_0) V(g7505_1)
.control
pre_osdi test_osdi_win/bsimbulk107.osdi
pre_osdi osdi_libs/bsimbulk107.osdi
unset ngdebug
save V(g7529_1) V(g7509_0) V(g7484_1) V(g7477_1) V(g7460_0) V(g7503_1) V(g7522_0) V(g7485_1) V(g7453_0) V(g7474_0) V(g7500_0) V(g7514_0) V(g7546_1) V(g7549_0) V(g7467_0) V(g7491_0) V(g7456_0) V(g7495_1) V(g7545_0) V(g7473_0) V(g7541_0) V(g7448_1) V(g7525_1) V(g7550_1) V(g165_1) V(g7510_1) V(g7535_1) V(g7534_1) V(g7469_1) V(g7476_0) V(g7517_1) V(g7537_0) V(g7489_1) V(g7521_1) V(g7486_0) V(g7533_1) V(g7449_0) V(g7447_0) V(g7528_0) V(g7513_1) V(g7548_0) V(g7544_1) V(g7552_0) V(g7540_1) V(g7507_0) V(g7481_0) V(g7455_0) V(g7502_1) V(g7446_1) V(g7478_1) V(g7470_0) V(g7526_0) V(g7494_1) V(g7452_1) V(g7463_0) V(g7532_1) V(g7512_0) V(g7527_0) V(g7451_0) V(g7472_0) V(g7498_1) V(g7475_0) V(g7536_0) V(g7488_1) V(g7493_1) V(g7551_1) V(g7482_0) V(g7487_1) V(g7501_1) V(g7520_1) V(g7516_1) V(g7450_1) V(g7508_0) V(g7458_1) V(g7479_1) V(g7506_1) V(g7499_0) V(g7471_0) V(g7465_1) V(g7464_1) V(g7543_1) V(g7524_0) V(g7539_1) V(g7468_1) V(g7459_0) V(g7504_1) V(g7515_1) V(g7492_1) V(g7511_0) V(g7462_1) V(g7530_0) V(g7497_1) V(g7454_1) V(g7519_1) V(g7531_0) V(g7547_0) V(g7483_1) V(g7466_1) V(g7480_1) V(g7523_1) V(g7496_0) V(g7538_0) V(g7490_1) V(g7518_1) V(g7461_0) V(g7542_0) V(g7457_0) V(g7505_1)

View File

@ -15,7 +15,7 @@ VB bb 0 0
N1 dd gg ss bb BSIMBULK_osdi_N W=500n L=90n
.control
pre_osdi test_osdi_win/bsimbulk107.osdi
pre_osdi osdi_libs/bsimbulk107.osdi
set xbrushwidth=3
* a DC sweep: drain, gate
dc Vd 0 1.6 0.01 VG 0 1.6 0.2

View File

@ -16,7 +16,7 @@ VB bb 0 0
N1 dd gg ss bb BSIMBULK_osdi_P W=500n L=90n
.control
pre_osdi test_osdi_win/bsimbulk107.osdi
pre_osdi osdi_libs/bsimbulk107.osdi
set xbrushwidth=3
* a DC sweep: drain, gate
*op

View File

@ -17,7 +17,7 @@ vbsp 44 0 0
.control
* Load the models dynamically
pre_osdi test_osdi_win/bsimbulk107.osdi
pre_osdi osdi_libs/bsimbulk107.osdi
set xgridwidth=2
set xbrushwidth=3

View File

@ -28,7 +28,7 @@ Xinv6 vi vo supply 0 mg_inv
.tran 0.1p 1n
.control
pre_osdi test_osdi_win/bsimcmg.osdi
pre_osdi osdi_libs/bsimcmg.osdi
set xbrushwidth=3
run
plot i(vss)

View File

@ -27,7 +27,7 @@ Xinv5 4 vo supply 0 mg_inv
.print tran v(vi) v(vo)
.control
pre_osdi test_osdi_win/bsimcmg.osdi
pre_osdi osdi_libs/bsimcmg.osdi
set xbrushwidth=3
run
plot v(vi) v(vo)

View File

@ -16,7 +16,7 @@ VB bb 0 0
N1 dd gg ss bb BSIMCMG_osdi_N ; W=5u L=0.2u
.control
pre_osdi test_osdi_win/bsimcmg.osdi
pre_osdi osdi_libs/bsimcmg.osdi
set xbrushwidth=3
* a DC sweep: drain, gate
dc Vd 0 2.5 0.01 VG 0 2.5 0.5

View File

@ -16,7 +16,7 @@ VB bb 0 0
N1 dd gg ss bb BSIMCMG_osdi_P
.control
pre_osdi test_osdi_win/bsimcmg.osdi
pre_osdi osdi_libs/bsimcmg.osdi
set xbrushwidth=3
* a DC sweep: drain, gate
dc Vd 0 -1.8 -0.01 VG 0 -1.8 -0.3

View File

@ -45,7 +45,7 @@ Xinv17 17 1 supply 0 mg_inv
.measure tran delay_per_stage param='period/34'
.control
pre_osdi test_osdi_win/bsimcmg.osdi
pre_osdi osdi_libs/bsimcmg.osdi
set xbrushwidth=3
run
plot v(1)

View File

@ -18,7 +18,7 @@ NN1 vout vin 0 0 BSIMCMG_osdi_N
.tran 10n 2u
.control
pre_osdi test_osdi_win/bsimcmg.osdi
pre_osdi osdi_libs/bsimcmg.osdi
set xbrushwidth=3
run
plot v(vout) v(vin)

View File

@ -32,7 +32,7 @@ Rdt dt 0 1G
.include Modelcards/model-card-hicumL0V1p11_mod.lib
.SAVE V(D) V(CLK) V(Q)
.control
pre_osdi test_osdi_win/HICUML0-2.osdi
pre_osdi osdi_libs/HICUML0-2.osdi
TRAN 0.25p 5n
rusage
set color0=white

View File

@ -35,7 +35,7 @@ V1 VEE GND -5.2
.tran 0.02n 200n
.control
pre_osdi test_osdi_win/HICUML0-2.osdi
pre_osdi osdi_libs/HICUML0-2.osdi
run
rusage
plot out9 xlimit 100n 110n

View File

@ -18,7 +18,7 @@ V3 In2 GND dc -1.75 pulse(-1.75 -0.9 0 1n 1n 2.5u 5u)
Rt1 DT GND 1G
.tran 0.1n 100u
.control
pre_osdi test_osdi_win/HICUML0-2.osdi
pre_osdi osdi_libs/HICUML0-2.osdi
run
plot a1 a2+2 in1+4 in2+6
.endc

View File

@ -8,7 +8,7 @@ XQ1 C B 0 S DT hicumL0V1p1_c_sbt
Rdt dt 0 1G
.control
pre_osdi test_osdi_win/HICUML0-2.osdi
pre_osdi osdi_libs/HICUML0-2.osdi
dc vb 0.2 1.4 0.01
set xbrushwidth=2
plot abs(i(vc)) abs(i(vb)) abs(i(vs)) ylimit 0.1p 100m ylog

View File

@ -8,7 +8,7 @@ X1 C B 0 S DT hicumL0V1p1_c_sbt
Rdt dt 0 1G
.control
pre_osdi test_osdi_win/HICUML0-2.osdi
pre_osdi osdi_libs/HICUML0-2.osdi
dc vc 0.0 3.0 0.05 ib 10u 100u 10u
set xbrushwidth=2
plot abs(i(vc))

View File

@ -5,11 +5,12 @@ MEXTRAM Gummel Test Ic,b,s=f(Vc,Ib)
VB B 0 0.5
VC C 0 2.0
VS S 0 0.0
NQ1 C B 0 S DT BJTRF1
NQ1 C B 0 S dt BJTRF1
.control
pre_osdi test_osdi_win/bjt504t.osdi
pre_osdi osdi_libs/bjt504t.osdi
dc vb 0.2 1.4 0.01
set xbrushwidth=2
plot abs(i(vc)) abs(i(vb)) abs(i(vs)) ylog xlimit 0.3 1.4 ylimit 1e-12 100e-3
plot abs(i(vc))/abs(i(vb)) vs abs(-i(vc)) xlog xlimit 1e-09 10e-3 ylimit 0 150
.endc

View File

@ -8,8 +8,9 @@ VS S 0 0.0
NQ1 C B 0 S T BJTRF1
.control
pre_osdi test_osdi_win/bjt504t.osdi
dc vc 0 6.0 0.05 ib 1u 8u 1u
pre_osdi osdi_libs/bjt504t.osdi
dc vc 0 6.0 0.05 ib 0 8u 1u
set xbrushwidth=2
plot abs(i(vc)) xlabel Vce title Output-Characteristic
.endc

View File

@ -67,7 +67,7 @@ c2 z vss 0.576f
.control
* Load the models dynamically
pre_osdi test_osdi_win/bsimbulk107.osdi test_osdi_win/psp103.osdi
pre_osdi osdi_libs/bsimbulk107.osdi osdi_libs/psp103.osdi
* Run the simulation
run
* Plotting

View File

@ -27,7 +27,7 @@ c2 z vss 0.576f
.dc V1 0 'vcc' 'vcc/100'
.control
pre_osdi test_osdi_win/bsimbulk107.osdi
pre_osdi osdi_libs/bsimbulk107.osdi
run
*set nolegend
set xbrushwidth=3

View File

@ -53,7 +53,7 @@ c2 z vss 0.576f
.dc V1 0 'vcc' 'vcc/100'
.control
pre_osdi test_osdi_win/psp103.osdi
pre_osdi osdi_libs/psp103.osdi
run
*set nolegend
set xbrushwidth=2

View File

@ -89225,7 +89225,7 @@ c2 z vss 0.834f
*.print tran V(g7529_1) V(g7509_0) V(g7484_1) V(g7477_1) V(g7460_0) V(g7503_1) V(g7522_0) V(g7485_1) V(g7453_0) V(g7474_0) V(g7500_0) V(g7514_0) V(g7546_1) V(g7549_0) V(g7467_0) V(g7491_0) V(g7456_0) V(g7495_1) V(g7545_0) V(g7473_0) V(g7541_0) V(g7448_1) V(g7525_1) V(g7550_1) V(g165_1) V(g7510_1) V(g7535_1) V(g7534_1) V(g7469_1) V(g7476_0) V(g7517_1) V(g7537_0) V(g7489_1) V(g7521_1) V(g7486_0) V(g7533_1) V(g7449_0) V(g7447_0) V(g7528_0) V(g7513_1) V(g7548_0) V(g7544_1) V(g7552_0) V(g7540_1) V(g7507_0) V(g7481_0) V(g7455_0) V(g7502_1) V(g7446_1) V(g7478_1) V(g7470_0) V(g7526_0) V(g7494_1) V(g7452_1) V(g7463_0) V(g7532_1) V(g7512_0) V(g7527_0) V(g7451_0) V(g7472_0) V(g7498_1) V(g7475_0) V(g7536_0) V(g7488_1) V(g7493_1) V(g7551_1) V(g7482_0) V(g7487_1) V(g7501_1) V(g7520_1) V(g7516_1) V(g7450_1) V(g7508_0) V(g7458_1) V(g7479_1) V(g7506_1) V(g7499_0) V(g7471_0) V(g7465_1) V(g7464_1) V(g7543_1) V(g7524_0) V(g7539_1) V(g7468_1) V(g7459_0) V(g7504_1) V(g7515_1) V(g7492_1) V(g7511_0) V(g7462_1) V(g7530_0) V(g7497_1) V(g7454_1) V(g7519_1) V(g7531_0) V(g7547_0) V(g7483_1) V(g7466_1) V(g7480_1) V(g7523_1) V(g7496_0) V(g7538_0) V(g7490_1) V(g7518_1) V(g7461_0) V(g7542_0) V(g7457_0) V(g7505_1)
.control
pre_osdi test_osdi_win/psp103.osdi
pre_osdi osdi_libs/psp103.osdi
unset ngdebug
save V(g7529_1) V(g7509_0) V(g7484_1) V(g7477_1) V(g7460_0) V(g7503_1) V(g7522_0) V(g7485_1) V(g7453_0) V(g7474_0) V(g7500_0) V(g7514_0) V(g7546_1) V(g7549_0) V(g7467_0) V(g7491_0) V(g7456_0) V(g7495_1) V(g7545_0) V(g7473_0) V(g7541_0) V(g7448_1) V(g7525_1) V(g7550_1) V(g165_1) V(g7510_1) V(g7535_1) V(g7534_1) V(g7469_1) V(g7476_0) V(g7517_1) V(g7537_0) V(g7489_1) V(g7521_1) V(g7486_0) V(g7533_1) V(g7449_0) V(g7447_0) V(g7528_0) V(g7513_1) V(g7548_0) V(g7544_1) V(g7552_0) V(g7540_1) V(g7507_0) V(g7481_0) V(g7455_0) V(g7502_1) V(g7446_1) V(g7478_1) V(g7470_0) V(g7526_0) V(g7494_1) V(g7452_1) V(g7463_0) V(g7532_1) V(g7512_0) V(g7527_0) V(g7451_0) V(g7472_0) V(g7498_1) V(g7475_0) V(g7536_0) V(g7488_1) V(g7493_1) V(g7551_1) V(g7482_0) V(g7487_1) V(g7501_1) V(g7520_1) V(g7516_1) V(g7450_1) V(g7508_0) V(g7458_1) V(g7479_1) V(g7506_1) V(g7499_0) V(g7471_0) V(g7465_1) V(g7464_1) V(g7543_1) V(g7524_0) V(g7539_1) V(g7468_1) V(g7459_0) V(g7504_1) V(g7515_1) V(g7492_1) V(g7511_0) V(g7462_1) V(g7530_0) V(g7497_1) V(g7454_1) V(g7519_1) V(g7531_0) V(g7547_0) V(g7483_1) V(g7466_1) V(g7480_1) V(g7523_1) V(g7496_0) V(g7538_0) V(g7490_1) V(g7518_1) V(g7461_0) V(g7542_0) V(g7457_0) V(g7505_1)

View File

@ -42,7 +42,7 @@ vbsp 44 0 0
.control
* Load the models dynamically
pre_osdi test_osdi_win/psp103.osdi
pre_osdi osdi_libs/psp103.osdi
set xgridwidth=2
set xbrushwidth=3

View File

@ -53,7 +53,7 @@ c2 z vss 0.576f
.dc V1 0 'vcc' 'vcc/100'
.control
pre_osdi test_osdi_win/psp103.osdi
pre_osdi osdi_libs/psp103.osdi
run
*set nolegend
set xbrushwidth=2

View File

@ -23,7 +23,7 @@ nm1 d g s b nch
*.include Modelcards/psp103_nmos.mod
.control
pre_osdi test_osdi_win/psp103.osdi
pre_osdi osdi_libs/psp103.osdi
dc vd 0 2.0 0.05 vg 0 1.5 0.25
plot i(vs)
dc vg 0 1.5 0.05 vb 0 -3.0 -1

View File

@ -19,7 +19,7 @@ nm1 d g s b pch
*
.option temp=21
.control
pre_osdi test_osdi_win/psp103.osdi
pre_osdi osdi_libs/psp103.osdi
dc vd 0 -2.0 -0.05 vg 0 -1.5 -0.25 ; saturation
plot i(vs)
dc vg 0 -1.5 -0.05 vb 0 3.0 1

View File

@ -56,7 +56,7 @@ c2 z vss 0.576f
.tran 10p 10n uic
.control
pre_osdi test_osdi_win/psp103.osdi
pre_osdi osdi_libs/psp103.osdi
run
set xbrushwidth=3
plot in

View File

@ -19,7 +19,7 @@ nm1 d g s b nch
*
.option temp=21
.control
pre_osdi test_osdi_win/psp103.osdi
pre_osdi osdi_libs/psp103.osdi
set xbrushwidth=2
dc vg 0 1.5 0.02 vb -3 0 0.5
plot abs(i(vd))

View File

@ -7,7 +7,7 @@ NRr2_cmc 1 0 rmodel w=1u l=20u isnoisy=1
.model rmodel r2_cmc(level=2 rsh=200 xl=0.2u xw=-0.05u p3=0.12 q3=1.6 p2=0.015 q2=3.8 tc1=1.5e-4 tc2=7e-7)
.control
pre_osdi test_osdi_win/r2_cmc.osdi
pre_osdi osdi_libs/r2_cmc.osdi
op
let res = v(1) / -v1#branch
print res

View File

@ -2869,8 +2869,10 @@ static char *inp_spawn_brace(char *s)
removes " " quotes, returns lower case letters,
replaces non-printable characters with '_', however if
non-printable character is the only character in a line,
replace it by '*'. If there is a XSPICE code model .model
line with file input, keep quotes and case for the file path.
replace it by '*'. Leave quotes in .param, .subckt and x
(subcircuit instance) cards to allow string-valued parameters.
If there is a XSPICE code model .model line with file input,
keep quotes and case for the file path.
*-------------------------------------------------------------------------*/
void inp_casefix(char *string)
@ -2883,20 +2885,23 @@ void inp_casefix(char *string)
return;
}
if (string) {
bool keepquotes;
#ifdef XSPICE
/* special treatment of code model file input */
char* tmpstr = NULL;
bool keepquotes = ciprefix(".model", string);
if (keepquotes){
/* Special treatment of code model file input. */
if (ciprefix(".model", string))
tmpstr = strstr(string, "file=");
keepquotes = keepquotes && tmpstr;
}
#endif
keepquotes = ciprefix(".param", string); // Allow string params
while (*string) {
#ifdef XSPICE
/* exclude file name inside of quotes from getting lower case,
keep quotes to enable spaces in file path */
if (keepquotes && string == tmpstr) {
if (string == tmpstr) {
string = string + 6; // past first quote
while (*string && *string != '"')
string++;
@ -2907,12 +2912,13 @@ void inp_casefix(char *string)
}
#endif
if (*string == '"') {
*string++ = ' ';
if (!keepquotes)
*string++ = ' ';
while (*string && *string != '"')
string++;
if (*string == '\0')
continue; /* needed if string is "something ! */
if (*string == '"')
if (*string == '"' && !keepquotes)
*string = ' ';
}
if (*string && !isspace_c(*string) && !isprint_c(*string))
@ -5054,24 +5060,40 @@ static int inp_split_multi_param_lines(struct card *card, int line_num)
char *beg_param, *end_param;
bool get_expression = FALSE;
bool get_paren_expression = FALSE;
int expression_depth = 0;
int paren_depth = 0;
beg_param = skip_back_ws(equal_ptr, curr_line);
beg_param = skip_back_non_ws(beg_param, curr_line);
end_param = skip_ws(equal_ptr + 1);
while (*end_param != '\0' &&
(!isspace_c(*end_param) || get_expression ||
get_paren_expression)) {
if (*end_param == '{')
get_expression = TRUE;
if (*end_param == '(')
get_paren_expression = TRUE;
if (*end_param == '}')
get_expression = FALSE;
if (*end_param == ')')
get_paren_expression = FALSE;
end_param++;
while (*end_param && !isspace_c(*end_param)) {
/* Advance over numeric or string expression. */
if (*end_param == '"') {
/* RHS is quoted string. */
end_param++;
while (*end_param != '\0' && *end_param != '"')
end_param++;
if (*end_param == '"')
end_param++;
} else {
while (*end_param != '\0' && *end_param != '"' &&
(!isspace_c(*end_param) ||
expression_depth || paren_depth)) {
if (*end_param == ',' && paren_depth == 0)
break;
if (*end_param == '{')
++expression_depth;
if (*end_param == '(')
++paren_depth;
if (*end_param == '}' && expression_depth > 0)
--expression_depth;
if (*end_param == ')' && paren_depth > 0)
--paren_depth;
end_param++;
}
}
}
if (end_param[-1] == ',')

View File

@ -9,6 +9,7 @@
#include "ngspice/bool.h"
void pscat(DSTRINGPTR s, const char *str, const char *stop);
void pscopy(DSTRINGPTR s, const char *str, const char *stop);
void scopyd(DSTRINGPTR dst, const DSTRINGPTR src);
void scopys(DSTRINGPTR a, const char *b);

View File

@ -123,21 +123,26 @@ scopys(DSTRINGPTR s, const char *t) /* returns success flag */
}
/* Copy until stop char (exclusive) or end of string if none given */
/* Concatentate until stop char (exclusive) or end of string if none given */
void
pscopy(DSTRINGPTR dstr_p, const char *t, const char *stop)
pscat(DSTRINGPTR dstr_p, const char *t, const char *stop)
{
if (!stop) { /* locate end of string if no stop char given */
stop = strchr(t, '\0');
}
ds_clear(dstr_p);
if (ds_cat_mem(dstr_p, t, (size_t) (stop - t)) != DS_E_OK) {
fprintf(stderr, "Error: DS could not copy partially string %s\n", t);
controlled_exit(-1);
}
} /* end of function pscat */
return;
/* Copy until stop char (exclusive) or end of string if none given */
void
pscopy(DSTRINGPTR dstr_p, const char *t, const char *stop)
{
ds_clear(dstr_p);
pscat(dstr_p, t, stop);
} /* end of function pscopy */

View File

@ -18,9 +18,9 @@ extern int nupa_eval(struct card *card);
extern void nupa_signal(int sig);
extern void nupa_scan(const struct card *card);
extern void nupa_list_params(FILE *cp_out);
extern double nupa_get_param(char *param_name, int *found);
extern double nupa_get_param(const char *param_name, int *found);
extern const char *nupa_get_string_param(const char *param_name);
extern void nupa_add_param(char *param_name, double value);
extern void nupa_add_inst_param(char *param_name, double value);
extern void nupa_copy_inst_dico(void);
extern void nupa_del_dicoS(void);
extern int nupa_add_dicoslist(void);

View File

@ -68,3 +68,4 @@ void nupa_subcktexit(dico_t *);
entry_t *entrynb(dico_t *dico, char *s);
entry_t *attrib(dico_t *, NGHASHPTR htable, char *t, char op);
void del_attrib(void *);
void nupa_copy_inst_entry(char *param_name, entry_t *proto);

View File

@ -415,6 +415,9 @@ dump_symbol_table(NGHASHPTR htable_p, FILE *fp)
{
if (entry->tp == NUPA_REAL)
fprintf(fp, " ---> %s = %g\n", entry->symbol, entry->vl);
else if (entry->tp == NUPA_STRING)
fprintf(fp, " ---> %s = \"%s\"\n",
entry->symbol, entry->sbbase);
}
}
@ -456,8 +459,7 @@ nupa_list_params(FILE *fp)
* Otherwise, we have to exhaust all of the tables including the global
* table.
* ----------------------------------------------------------------- */
double
nupa_get_param(char *param_name, int *found)
static entry_t *nupa_get_entry(const char *param_name)
{
dico_t *dico = dicoS; /* local copy for speed */
int depth; /* nested subcircit depth */
@ -465,21 +467,40 @@ nupa_get_param(char *param_name, int *found)
for (depth = dico->stack_depth; depth >= 0; depth--) {
NGHASHPTR htable_p = dico->symbols[depth];
if (htable_p) {
entry_t *entry = (entry_t *) nghash_find(htable_p, param_name);
if (entry) {
*found = 1;
return entry->vl;
}
entry_t *entry;
entry = (entry_t *)nghash_find(htable_p, (void *)param_name);
if (entry)
return entry;
}
}
return NULL;
}
double
nupa_get_param(const char *param_name, int *found)
{
entry_t *entry = nupa_get_entry(param_name);
if (entry && entry->tp == NUPA_REAL) {
*found = 1;
return entry->vl;
}
*found = 0;
return 0;
}
const char *
nupa_get_string_param(const char *param_name)
{
entry_t *entry = nupa_get_entry(param_name);
if (entry && entry->tp == NUPA_STRING)
return entry->sbbase;
return NULL;
}
void
nupa_add_param(char *param_name, double value)
static void
nupa_copy_entry(entry_t *proto)
{
dico_t *dico = dicoS; /* local copy for speed */
entry_t *entry; /* current entry */
@ -491,18 +512,32 @@ nupa_add_param(char *param_name, double value)
htable_p = dico->symbols[dico->stack_depth];
entry = attrib(dico, htable_p, param_name, 'N');
entry = attrib(dico, htable_p, proto->symbol, 'N');
if (entry) {
entry->vl = value;
entry->tp = NUPA_REAL;
entry->ivl = 0;
entry->sbbase = NULL;
entry->vl = proto->vl;
entry->tp = proto->tp;
entry->ivl = proto->ivl;
entry->sbbase = proto->sbbase;
}
}
void
nupa_add_inst_param(char *param_name, double value)
nupa_add_param(char *param_name, double value)
{
entry_t entry;
entry.symbol = param_name;
entry.vl = value;
entry.tp = NUPA_REAL;
entry.ivl = 0;
entry.sbbase = NULL;
nupa_copy_entry(&entry);
}
void
nupa_copy_inst_entry(char *param_name, entry_t *proto)
{
dico_t *dico = dicoS; /* local copy for speed */
entry_t *entry; /* current entry */
@ -512,10 +547,10 @@ nupa_add_inst_param(char *param_name, double value)
entry = attrib(dico, dico->inst_symbols, param_name, 'N');
if (entry) {
entry->vl = value;
entry->tp = NUPA_REAL;
entry->ivl = 0;
entry->sbbase = NULL;
entry->vl = proto->vl;
entry->tp = proto->tp;
entry->ivl = proto->ivl;
entry->sbbase = proto->sbbase;
}
}
@ -542,7 +577,7 @@ nupa_copy_inst_dico(void)
entry;
entry = (entry_t *) nghash_enumerateRE(dico->inst_symbols, &iter))
{
nupa_add_param(entry->symbol, entry->vl);
nupa_copy_entry(entry);
dico_free_entry(entry);
}

View File

@ -232,7 +232,6 @@ message(dico_t *dico, const char *fmt, ...)
dico->oldline);
}
}
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
@ -275,7 +274,6 @@ dico_free_entry(entry_t *entry)
{
if (entry->symbol)
txfree(entry->symbol);
txfree(entry);
}
@ -339,7 +337,7 @@ dicostack_pop(dico_t *dico)
fprintf(stderr, "Error: DS could not add string %s\n", inst_name);
controlled_exit(-1);
}
nupa_add_inst_param(ds_get_buf(&param_name), entry->vl);
nupa_copy_inst_entry(ds_get_buf(&param_name), entry);
dico_free_entry(entry);
}
nghash_free(htable_p, NULL, NULL);
@ -440,6 +438,8 @@ del_attrib(void *entry_p)
entry_t *entry = (entry_t*) entry_p;
if(entry) {
tfree(entry->symbol);
if (entry->sbbase)
tfree(entry->sbbase);
tfree(entry);
}
}
@ -1085,6 +1085,79 @@ formula(dico_t *dico, const char *s, const char *s_end, bool *perror)
}
/* Check for a string expression, return end pointer or NULL.
* A string expression is a sequence of quoted strings and string
* variables, optionally enclosed by '{}' with no interventing space.
* If successful return pointer to next char, otherwise NULL.
* Evaluated string is returned in *qstr_p (may be NULL).
*/
static char *string_expr(dico_t *dico, DSTRINGPTR qstr_p,
const char *t, const char *t_end)
{
const char *tie;
bool ok = FALSE;
while (isblank(*t) && t < t_end)
++t;
if (qstr_p)
ds_clear(qstr_p);
for (; t < t_end; ) {
if (*t == '"') {
/* String constant. */
tie = ++t;
while (*t != '"' && t < t_end)
++t;
if (qstr_p)
pscat(qstr_p, tie, t);
if (*t == '"')
++t;
ok = TRUE;
continue;
}
if (*t == '{') {
/* Isolate and check wrapped identifier. */
tie = ++t;
while (t < t_end) {
if (*t == '}')
break;
++t;
}
} else {
/* Last option: naked string-valued param. */
tie = t;
t = fetchid(t, t_end);
if (t == tie )
return NULL;
}
/* Now pointers tie, t should bracket an identifier. */
{
DS_CREATE(lcl_str, 200);
entry_t *entry;
/* Formula is a single identifier. */
pscopy(&lcl_str, tie, t);
entry = entrynb(dico, ds_get_buf(&lcl_str));
ds_free(&lcl_str);
if (entry && (entry->tp == NUPA_STRING)) {
if (qstr_p)
pscat(qstr_p, entry->sbbase, NULL);
ok = TRUE;
} else {
return NULL;
}
}
if (*t == '}')
++t;
}
return ok ? (char *)t : NULL;
}
/* stupid, produce a string representation of a given double
* to be spliced back into the circuit deck
* we want *exactly* 25 chars, we have
@ -1113,7 +1186,8 @@ evaluate_expr(dico_t *dico, DSTRINGPTR qstr_p, const char *t, const char * const
double u;
ds_clear(qstr_p);
if (string_expr(dico, qstr_p, t, t_end))
return 0;
u = formula(dico, t, t_end, &err);
if (err)
return err;
@ -1247,38 +1321,31 @@ getword(const char *s, DSTRINGPTR tstr_p)
static char *
getexpress(nupa_type *type, DSTRINGPTR tstr_p, const char *s)
getexpress(dico_t *dico, nupa_type *type, DSTRINGPTR tstr_p, const char *s)
/* returns expression-like string until next separator
Input i=position before expr, output i=just after expr, on separator.
returns tpe=='R' if (numeric, 'S' if (string only
*/
{
const char * const s_end = s + strlen(s);
const char *s_end = s + strlen(s);
const char *p;
nupa_type tpe;
while ((s < s_end - 1) && ((unsigned char)(* s) <= ' '))
s++; /*white space ? */
if (*s == '"') { /* string constant */
s++;
p = s;
while ((p < s_end - 1) && (*p != '"'))
p++;
do
p++;
while ((p < s_end) && ((unsigned char)(*p) <= ' '));
/* Check for injected semicolon separator in assignment list. */
p = strchr(s, ';');
if (p)
s_end = p;
p = string_expr(dico, NULL, s, s_end);
if (p) {
tpe = NUPA_STRING;
} else {
if (*s == '{')
s++;
p = s;
for (; p < s_end; p++) {
@ -1304,7 +1371,6 @@ getexpress(nupa_type *type, DSTRINGPTR tstr_p, const char *s)
}
}
}
tpe = NUPA_REAL;
}
@ -1313,9 +1379,6 @@ getexpress(nupa_type *type, DSTRINGPTR tstr_p, const char *s)
if (*p == '}')
p++;
if (tpe == NUPA_STRING)
p++; /* beyond quote */
if (type)
*type = tpe;
@ -1334,7 +1397,8 @@ nupa_assignment(dico_t *dico, const char *s, char mode)
/* s has the format: ident = expression; ident= expression ... */
const char * const s_end = s + strlen(s);
const char *p = s;
const char *tmp;
char *sval = NULL;
bool error = 0;
nupa_type dtype;
int wval = 0;
@ -1369,23 +1433,26 @@ nupa_assignment(dico_t *dico, const char *s, char mode)
break;
}
p = getexpress(&dtype, &ustr, p + 1) + 1;
p = getexpress(dico, &dtype, &ustr, p + 1) + 1;
tmp = ds_get_buf(&ustr);
if (dtype == NUPA_REAL) {
const char *tmp = ds_get_buf(&ustr);
rval = formula(dico, tmp, tmp + strlen(tmp), &error);
if (error) {
message(dico,
" Formula() error.\n"
" %s\n", s);
" |%s| : |%s|=|%s|\n", s, ds_get_buf(&tstr), ds_get_buf(&ustr));
break;
}
} else if (dtype == NUPA_STRING) {
wval = (int) (p - s);
DS_CREATE(sstr, 200);
string_expr(dico, &sstr, tmp, tmp + strlen(tmp));
sval = copy(ds_get_buf(&sstr));
ds_free(&sstr);
}
error = nupa_define(dico, ds_get_buf(&tstr), mode /* was ' ' */ ,
dtype, rval, wval, NULL);
dtype, rval, wval, sval);
if (error)
break;
@ -1445,9 +1512,10 @@ nupa_subcktcall(dico_t *dico, const char *s, const char *x,
/***** first, analyze the subckt definition line */
n = 0; /* number of parameters if any */
scopys(&tstr, s);
/* Get the subcircuit name in subname. */
const char *j2 = strstr(ds_get_buf(&tstr), "subckt");
if (j2) {
j2 = skip_ws(j2 + 6); /* skip subckt and whitespace */
@ -1456,6 +1524,8 @@ nupa_subcktcall(dico_t *dico, const char *s, const char *x,
err = message(dico, " ! a subckt line!\n");
}
/* Scan the .subckt line for assignments, copying templates to idlist. */
const char *i2 = strstr(ds_get_buf(&tstr), "params:");
if (i2) {
@ -1510,7 +1580,7 @@ nupa_subcktcall(dico_t *dico, const char *s, const char *x,
char * const t_p = ds_get_buf(&tstr);
char *jp = NULL;
/* search for the last occurence of `subname' in the given line */
/* Search for the last occurence of `subname' in the call line. */
for (;;) {
char *next_p = search_isolated_identifier(jp ? jp + 1 : t_p,
ds_get_buf(&subname));
@ -1528,7 +1598,6 @@ nupa_subcktcall(dico_t *dico, const char *s, const char *x,
/* jp is pointing to the 1st position of arglist now */
while (*jp) {
/* try to fetch valid arguments */
char *kp = jp;
ds_clear(&ustr);
@ -1538,13 +1607,16 @@ nupa_subcktcall(dico_t *dico, const char *s, const char *x,
jp = skip_non_ws(kp);
pscopy(&ustr, kp, jp);
} else if (*kp == '{') {
jp = getexpress(NULL, &ustr, jp);
jp = getexpress(dico, NULL, &ustr, jp);
} else {
jp++;
if ((unsigned char) (*kp) > ' ')
message(dico, "Subckt call, symbol %c not understood\n", *kp);
}
/* Substitute the parameter for one of the '$' characters
* in idlist.
*/
char * const u_p = ds_get_buf(&ustr);
if (*u_p) {
char * const idlist_p = ds_get_buf(&idlist);