affbe5f5创建于 2025年3月25日历史提交
文件最后提交记录最后更新时间
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
readme.txt

README.TXT the minimal Numparam documentation


Numparam: an add-on library for electronic circuit analysis front-ends Copyright (C) 2002 Georg Post

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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

CONTENTS

A. The Numparam library B. Circuit description with Numparam (in lieu of a tutorial) C. Reference section D. Installation E. Theory of operation F. Files in this package G. Known bugs

A. The Numparam library:

The spice-3f(x) front end lacks some features of commercial derivatives, such as the ability to define numerical attributes of devices by symbols or by constant (at circuit-expansion time) numerical expressions. Numerical parameters - other than node names - for subcircuits are also commonly available in these non-free Spices.

This library provides a retrofit to the Spice circuit description language to add these features. By design, the new code is organized as an independent library which does not import any Spice header files and whose only interface to Spice is a set of three function headers. The only place where these functions are called - if a new compile-time option for Spice is set - is the code file src/lib/fte/subckt.c. There are no patches anywhere else.

The purpose of this minimal coupling was to freely license the additional code. It is distributed under the GNU-LGPL and thus can be linked to the original Spice which is open-source software but maintains a special license. (As I read somewhere, Berkeley Spice is reserved to people friendly to the USA). Due to GPL-type requirements, I cannot merge any lines from Spice with the new code, and I cannot avoid redundancies, such as one more symbol table manager and the umpteenth arithmetic expression parser.

Coding style of my add-on is a bit personal. Using a set of keyword-hiding macros, it is closer to Pascal and/or Basic than to authentic C programs. Most of it originated from my initial Turbo Pascal preprocessors that have been translated to C. After all, I'm definitely not "friendly to the C language". Even in disguise, the code is pure Ansi-C and compiles without a warning under the severest settings of gcc (under GNU/Linux) or Turbo C++ (under MS-DOS). For C hardliners, I include the 'washprog' utility which downgrades the source code to the common C look-&-feel. Extreme purists might apply some appropriate "indent" utility, in addition.

B. Circuit description with Numparam (in lieu of a tutorial).

As we now know, all the text entry to Spice comes in two separate languages:

  • a circuit description language (CDL) which defines the electronic hardware.
  • an analysis job and data management language (JDML) which may be used as an interactive shell or in batch files.

In the circuit description "CDL" file, the design is typically organized as a hierarchical set of subcircuits which are connected together in the 'main' circuit (they are "called", like procedures in a general-purpose programming language). CDL is line-oriented, with a recognizer role assigned to the first non-space character of a line. (In the ancient times of data processing, a line was called a "card".) For example, '*' introduces comment lines. 'C' places a capacitor device in the circuit, 'R' a resistor, 'L' an inductor, and so on. 'X' signals the "call" of a subcircuit. Character '+' introduces a continuation line (the way to split exceedingly long lines into pieces).

A special class of lines that start with a dot '.' have control functions inside CDL: they do not add physical circuit elements. For instance, the control pair '.subckt' and '.ends' brackets a subcircuit definition section in CDL. In the old days of Spice-2, some of the functions now assigned to JDML were also inserted as dot cards. You can still insert pieces of JDML inside a CDL file, as a section enclosed within lines '.control' and '.endc' .

Example CDL file, a netlist of some double T RC-filter:

  • First-example .subckt myfilter in out Ra in p1 2k Rb p1 out 2k C1 p1 0 2nF Ca in p2 1nF Cb p2 out 1nF R1 p2 0 1k .ends myfilter

X1 input output myfilter V1 input 0 AC 1V .end

Let us recall what the Spice "front-end" essentially does to your circuit-description (CDL) file whenever it is submitted, either at program start-up or after some interactive JDML commands like 'edit' or 'source'. First, all the JDML sections in the file are sorted out and kept for later use (unless the file is pure JDML and thus immediately executed). Next, the hierarchy of subcircuits is expanded and an internal representation of the flattened circuit is stored, i.e. a set of CDL lines without any more 'X' and '.subckt' lines. This flat circuit is also known as the "netlist". Then, the netlist is translated into the internal data structures of Spice, essentially a sparse matrix of elements indexed by pairs of circuit nodes.

Finally, the mathematical analysis is carried out under the control of JDML, and output data may be stored, printed, plotted, compared, and so on. Analyses may be repeated under varying bias/frequency/time... conditions. But to change the circuit topology, the CDL must be edited and re-compiled.

Numparam-specific features of CDL :

The Numparam library is an enhancement of the Spice front-end which adds clarity and arithmetic functionality to the circuit description language.

The most wanted feature of a language is to have word-like symbols that take the place of specific values or objects. The dot-line

.param =

defines such symbols. For example, to describe a triple RC filter with identical values of components, we do not need to explicitly repeat constant numbers. The CDL code may go like this:

.param res= 1kohm // numparam allows comment tails like in C++ .param tau= 10ns // we want a time constant .param cap= tau/res // tau= RC, of course

.subckt triplerc in out R1 in p1 {res} C1 p1 0 {cap} R2 p1 p2 {res} C2 p2 0 {cap} R3 p2 out {res} C3 out 0 {cap} .ends

As you can see, the use of symbols anywhere in the circuit description requires the curly braces : { } This coding style is even more interesting if circuit elements have known fixed ratios (Butterworth filters and the like) and we only need to touch one value (a time constant) to tune the circuit.

Only numerical constants such as '30pF' may be used without enclosing braces. It is the braces that tell our CDL front-end to look up symbols and to crunch arithmetic expressions inside.

Obviously, it was restrictive that subcircuit definitions could only accept interface node names as symbolic parameters. With the following syntax of the .subckt line, we add numerical parameters:

.subckt ... params: = = ...

Example, a parameterized filter:

.subckt triplerc2 in out params: res=1kohm cap=50pF

  • all the following lines as above.
  • the specified default values are always overridden with X lines.

To call variants of such a subcircuit later on, we may write:

X1 in out1 triplerc2 {r1} {c1} X2 in out2 triplerc2 {2r1} {c1/2} X3 in out3 triplerc2 {3r1} {c1/3}

where the r1 and c1 symbols are defined in .param lines. So, we can use subcircuits with one or more parameters, the same way as Spice2 already allowed an area parameter for diodes and transistors.

Here is the first example, rewritten with parameters:

  • Param-example .param amplitude= 1V

.subckt myfilter in out

  • params: rval=100k cval= 100nF Ra in p1 {2rval} Rb p1 out {2rval} C1 p1 0 {2*cval} Ca in p2 {cval} Cb p2 out {cval} R1 p2 0 {rval} .ends myfilter

X1 input output myfilter 1k 1nF V1 input 0 AC {amplitude} .end

Note: Now, there is some possible confusion in Spice because of multiple numerical expression features. The .param lines and the braces expressions are evaluated in the front-end, that is, just after the subcircuit expansion. (Technically, the X lines are kept as comments in the expanded circuit so that the actual parameters can correctly be substituted ). So, after the netlist expansion and before the internal data setup, all number attributes in the circuit are known constants. However, there are some circuit elements in Spice which accept arithmetic expressions that are NOT evaluated at this point, but only later during circuit analysis. These are the arbitrary current and voltage sources. The syntactic difference is that "compile-time" expressions are within braces, but "run-time" expressions have no braces. To make things more complicated, the backend language JDML also accepts arithmetic/logic expressions that operate on its own scalar or vector data sets.

It would be desirable to have the same expression syntax, operator and function set, and precedence rules, for the three contexts mentioned above. In the current Numparam implementation, that goal is not yet achieved...

C. Reference section:

The Numparam add-on supports the following elements in the circuit description language.

  1. '.param' control lines to define symbolic numbers
  2. arithmetic expressions in place of any numeric constant
  3. formal and actual numeric parameters for subcircuit definition and 'call'.

NOT YET IMPLEMENTED: To activate the additional functions, put a line near the top of the CDL file: .option numparam

In the syntax description, means an alphanumeric identifier (<20 chars, starting with a letter) means an expression, composed of s, Spice numbers, and operators.

  1. The .param line: Syntax: .param = ; = ....

This line assigns numerical values to identifiers. More than one assignment per line is possible using the ';' separator. The .param lines inside subcircuits are copied per call, like any other line. All assignments are executed sequentially through the expanded circuit. Before its first use, a name must have been assigned a value.

  1. Brace expressions in cicuit elements: Syntax: { }

These are allowed in .model lines and in device lines, wherever only constant Spice numbers could be used in spice2/3. A Spice number is a floating point number with an optional scaling suffix, immediately glued to the numeric tokens (see below). Warning: {..} cannot be used to 'parameterize' node names or parts of names. ( We are not into obfuscated shell scripting ...) All identifiers used within an must have known values at the time when the line is evaluated, else an error is flagged.

  1. Subcircuit parameters: The syntax of a subcircuit definition header is: .subckt node node ... params: = =...

    node is an integer number or an identifier, for one of the external nodes. The 'params:' keyword introduces an optional section of the line. Each is a formal parameter, and each is either a Spice number or a brace expression. Inside the '.subckt' ... '.ends' context, each formal parameter may be used like any identifier that was defined on a .param control line. The parts are supposed to be default values of the parameters. However, in the current version of Numparam, they are not used and each invocation of the subcircuit must supply the exact number of actual parameters.

    The syntax of a subcircuit call (invocation) is: X node node ... ....

    Here is the symbolic name given to that instance of the subcircuit, is the name of a subcircuit defined beforehand. node node ... is
    the list of actual nodes where the subcircuit is connected. is either a Spice number or a brace expression { } . The sequence of items on the X line must exactly match the number and the order of formal parameters of the subcircuit.

  2. Symbol scope

    All Subcircuit and Model names are considered global and must be unique. The .param symbols that are defined outside of any '.subckt' ... '.ends' section are global. Inside such a section, the pertaining 'params:' symbols and any .param assignments are considered local: they mask any global identical names, until the .ends line is encountered. You cannot reassign to a global number inside a .subckt, a local copy is created instead. Scope nesting now works up to any level. For example, if the main circuit calls A which has a formal parameter xx, A calls B which has a param. xx, and B calls C which also has a formal param. xx, there will be three versions of 'xx' in the symbol table but only the most local one - belonging to C - is visible.

  3. Syntax of expressions ( optional parts within [ ...] ):

    An expression may be one of: where is either a Spice number or an identifier ( [ , ...] )
    ( )

    As expected, atoms, builtin function calls and stuff within parentheses are evaluated before the other operators. The operators are evaluated following a list of precedence close to the one of the C language. For equal precedence binary ops, evaluation goes left to right.

    Operators: Alias Internal symb. Precedence

    •                   -                   1     (unary -)
      

    not ! ! 1 (unary not) ** ^ ^ 2 (power)

    •                   *                   3     (multiply)
      

    / / 3 (divide) mod % % 3 (modulo) div \ \ 3 (integer divide)

    •                   +                   4     (add)
      
    •                   -                   4     (subtract)
      

    == = 5 (equality) <> != # 5 (un-equal) <= L 5 (less or equal)

    = G 5 (greater or equal) < < 5 (less than) > 5 (greater than) and && & 6 (and) or || | 7 (or)

    The result of logical operators is 1 or 0 , for True or False.

    Builtin functions: Internal ref.

    defined 0 (returns 1 if symbol is defined, else 0) sqr 1 sqrt 2 sin 3 cos 4 exp 5 ln 6 arctan 7 abs 8 pwr 9

    Scaling suffixes (any decorative alphanum. string may follow ...)

    g 1e9 meg 1e6 k 1e3 m 1e-3 u 1e-6 n 1e-9 p 1e-12 f 1e-15

Note: there are intentional redundancies in expression syntax, e.g. x^y , x**y and pwr(x,y) all have nearly the same result.

  1. Reserved words In addition to the above function names and to the verbose operators
    ( not and or div mod ), other words are reserved and cannot be used as parameter names. Historically, they come from a version of Numparam that was a full-blown macro language. I won't link that one to Spice, not before somebody proves to me that such a thing could be useful...

    and or not div mod if else end while macro funct defined include for to downto is var sqr sqrt sin cos exp ln arctan abs pwr

  2. Alternative syntax the & sign is tolerated to provide some 'historical' parameter notation: & as the first character of a line is equivalent to: .param Inside a line, the notation &(....) is equivalent to {....}, and &identifier means the same thing as {identifier} .

    This notation exists a bit for the same reason as my macros which wipe the curly braces out of the C language: entering those signs is a pain in the neck on IBM French-type keyboards. You hit, among others, a vanishingly small AltGr key which is squeezed by superfluous buttons that show ugly office-software logos...

    Comments in the style of C++ line trailers (//) are detected and erased. Warning: this is NOT possible in embedded .control parts of a source file, these JDML lines are outside of Numparam's scope. DOS-style carriage returns at line ends are difficult for JDML, too.

D. Installation

There are two versions of Spice on which this library has been tried: a. a 1997 version spice3f5 that was arranged for Red Hat Linux b. the version 14 of ngspice (will now be privileged for development)

On my system, the size of libnupa.a is about 47k, so this is the additional bloat that the spice3 and nutmeg binary programs will accumulate. ( The numparam source tarball weighs in for some 70k )

The common part to build the Numparam library is this:

  1. choose any directory you like for Numparam, let's call it $HACK.

  2. un-tar the .c and .h files and the rest, in Numparam's directory : tar xzvf numparam.tgz

  3. compile the lib sources with gcc -c -Wall:

gcc -c -ansi -pedantic -Wall spicenum.c nupatest.c xpressn.c mystring.c

  1. pre-link together the library part to numparam.o and libnupa.a:

ld -r -o numparam.o spicenum.o xpressn.o mystring.o ar -rcs libnupa.a spicenum.o xpressn.o mystring.o

  1. make the test executable nupatest:

    gcc -o nupatest nupatest.o spicenum.o xpressn.o mystring.o -lm

The script file 'mknumpar.sh' does all this (2-4).

5a. Link with the "third version of Spice3f5 for RedHat Linux 2.6" (1997)

do the following in the spice3f5 top-level directory:

  1. patch the file src/lib/fte/subckt.c : cp -biv $HACK/rhsubckt.c src/lib/fte/subckt.c
  2. edit src/bin/makeops , to add $HACK/libnupa.a to LIBS and LIBN.
  3. ./util/build linux
  4. ./util/build linux install

5b. Link procedure for ngspice version 14

I haven't yet a working knowledge of the 'automake/autoconf' system, so I'll describe the pedestrian hacks to get Numparam in. That's evil; the right way would need a configuration flag that chooses to make and to link the library. Only the top level files 'configure.in' and 'Makefile.am' should be revised to process the numparam option. (?) Help!

  1. replace the file src/frontend/subckt.c with Numparam's patched version : cp -biv $HACK/ngsubckt.c src/frontend/subckt.c
  2. run ./configure with a "LIBS prefix" to include numparam (see below)
  3. make
  4. make install

Here is one "prefixed" ngspice configure script that works on my system:

#!/bin/sh

ngconfig.sh

configure options for ngspice with numparam add-on

run this in ngspice's top-level directory

specify your Numparam directory

HACK=/home/post/spice3f5/hack

over-write the original subckt.c

cp -biv $HACK/ngsubckt.c src/frontend/subckt.c

my box needs CFLAGS on 1st run, else 'terminal.c' wont find 'termcap.h' ?

CFLAGS=-I/usr/include/ncurses
LIBS=$HACK/libnupa.a
./configure --without-x --prefix=/usr/local/ngsp

end of sample script

E. Theory of operation

Spice's front end does a lot of malloc/free type memory gymnastics and does not seem to care much about small leaks here and there. Numparam will do some malloc'ing in place of Spice (essentially the translated strings of the input deck) and rely on Spice to clean it up - or not - later on. My library will
clean up its private space only (the symbol tables) and will make some assumptions about the interface function calls coming from Spice. Here is the scenario supposed to be followed by Spice and Numparam:

  1. the patched codefile subckt.c imports the following header lines:

#define NUPADECKCOPY 0 #define NUPASUBSTART 1 #define NUPASUBDONE 2 #define NUPAEVALDONE 3

extern char * nupa_copy(char *s, int linenum); extern int nupa_eval(char *s, int linenum); extern int nupa_signal(int sig);

These are the three library functions called, i.e.

  • nupa_copy by inp_subcktexpand to preprocess all extended-syntax lines.
  • nupa_eval by inp_subcktexpand to do the parameter substitutions
  • nupa_signal with one of the 4 signals, from various places to send state information to the Numparam library.

The only places with numparam patches are the functions inp_subcktexpand() and its recursive subroutine doit(), in the file subckt.c . At this stage, we suppose that:

  • any .control sections are filtered out
  • any .include are expanded
  • any + continuation line chunks are glued together
  1. In the first phase, Numparam runs through the deck (whose .control sections have already been removed by Spice) to create copies of the lines without the extended syntax. Pointers to the original deck lines are kept and the copies are traditional Spice, with placeholders for symbols and expressions. Spice loses the originals and gets the bleached-out copies.

  2. The "doit()" circuit expansions are modified to keep more information. Contrary to the initial Spice code, now the subcircuit invocation lines are preserved as comments, which allows Numparam to update symbolic subcircuit parameters a bit later. Subcircuit exit lines are also copied and out-commented, to keep track of identifier scopes during the final pass.

If this seems waste of storage, just consider all those sloppy memory leaks in the circuit expansion code...

  1. The final wash-up is a sequential call to the library (nupa_eval()) line-by-line through the expanded circuit. By using its pointers to the original lines, Numparam recovers the added syntax features. It triggers all the symbol value computations and inserts constant numbers into the circuit definition lines, whose length must not change! This option is a kludge to avoid memory reallocation [ my intuitive fear is that these free() malloc() realloc() and friends swallow a lot of CPU time ? ].

  2. The termination signal at the end of inp_subcktexpand() tells the Numparam library to clean up its mess, release its pointers to the original Spice circuit description text, and to get prepared for another run. Note: Numparam frees the storage related to the original lines whose pointers have been stolen in phase 1.

In a future release, Numparam will be re-entrant, all its 'global' data being referenced via a handle which the client program should keep around.

F. Files in this package

The following Ansi C code files belong to Numparam:

general.h header file with macros to disguise the C language. stuff for an 'overflow-safe' string library ( whose biggest bug is that it indexes strings from 1 like Pascal).

numparam.h header file for numparam-specific symbols and functions

mystring.c collection of 'safer' character string (and misc.) functions. beware of the nasty Turbo Pascal conventions.

xpressn.c the interpreter of arithmetic/logical expressions

spicenum.c the interface part, functions that are called by Spice.

nupatest.c a stand-alone subcircuit expander, for test purpose.

washprog.c a program that washes all the above C files, including itself, to recover the crude syntax of the True Language (see below).

Patched versions of spice's subckt.c file incorporate the library calls and maybe try to repair some memory leaks (in rhsubckt.c, not yet tested).

rhsubckt.c for spice3f5 1997 Red Hat (src/lib/fte/subckt.c) ngsubckt.c for ngspice version 14 (src/frontend/subckt.c) subckt.dif 'diff' between ngsubckt.c and ngspice frontend/subckt.c

The following text, data and script files are also included:

readme.txt this documentation file downgrad.txt the substitution rules required for washprog.c mknumpar.sh script to make the library binaries ngconfig.sh sample script to run ./configure for ngspice

configure.in crappy ? Makefile.am crappy ?

testfile.nup a test text (nonsense circuit) for Numparam ?

So, if you are a Real Programmer, think that the Pascal amateurs confound programming with writing novels, and find those Basic greenhorns' style too childish, then execute the following two-liner first of all (should work on GNU/Linux, but it's not a speed monster) :

gcc -o washprog washprog.c mystring.c ./washprog *.c

You get all the *.c files in a version where the first character becomes an underbar, and the interior resembles to code. (although it lacks such powerful features as continue, break, goto, ?:-expressions, gets(), ... )

G. Known Bugs

First of all, lots of size limits - incompatible with the Spirit of the Gnu, who wants that everything may grow as much as malloc() can grab ...

  • circuit source code line length: 80 chars
  • circuit '+' extended code lines: 250 chars
  • number of source lines: 1000
  • number of lines in expanded circuit: 5000
  • length of numparam identifiers: 20 chars
  • number of numparam identifiers: 200
  • length of file names: 80 chars
  • significant digits in param results: 5
  • nesting depth of parentheses 9
  • nesting of subckt calls 10

All these constants should be in the header file but aren't.

After each circuit expansion, numparam asks a silly question of the "Abort/Continue" type. A debugging feature, to be killed soon.

The Numparam symbol table accumulates the following sets of names: subcircuits, models, global parameters, subcircuit arguments. Node names, however, are completely ignored.

Call the following "bugs" or "features":

  • A model/subckt name cannot be defined twice, even if local to a subcircuit.
  • The same name cannot design a model here, and a parameter elsewhere.
  • A subcircuit argument masks any global parameter of same name, anytime the subckt is invoked. Inside a .subckt context, .param assignments also have local scope and override global identical names.

It is wise to always use unique names for everything.

While Numparam is in 'early beta stage', I strongly suggest to use 'nupatest' first, on any 'parameterized' Spice circuit file, before starting the enhanced circuit analyser.

The command
nupatest foobar.cir produces an output file 'foobar.out' which is the expanded and parameter-reduced flat netlist. By the way, it produces error messages whenever it chokes on the source file. If nupatest succeeds, the spice+numparam combo should swallow it, too. Big bug: Nupatest does not yet prefix and infix things inside v() and i().

Numparam comes with two very experimental files 'configure.in' and 'Makefile.am' as an exercise of the automake/autoconf mechanisms. I certainly got a lot of things wrong and had to do eight steps to have it kind of work:

  1. edit/create configure.in
  2. edit/create Makefile.am
  3. run autoheader --> config.h.in
  4. run automake --foreign --add-missing --verbose --> Makefile.in
  5. run aclocal --> aclocal.m4
  6. run autoconf --> configure
  7. run ./configure --> Makefile config.h
  8. run make

Do we need all this, and -worse- do we need to repeat it whenever we touch 'configure.in' and/or 'Makefile.am' ? Help!

Please send your bug reports, improvements, flames etc. to the author: georg.post @ wanadoo.fr