------------------------------------------------------------------------
SPICEPRM - A Spice preprocessor for parameterized subcircuits (v 0.11)
Copyright (C) 1996 Andrew J. Borsa <andy@moose.mv.com>
------------------------------------------------------------------------

    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., 675 Mass Ave, Cambridge, MA 02139, USA.

------------------------------------------------------------------------

Spiceprm was written in the course of moving my engineering activities
to the Linux operating system.  My previous MSDOS spice package
permitted passing parameters to subcircuits.  The raw Berkely Spice
doesn't.   Anyone used to this feature knows the frustration of trying
to use a simulator without it.  This script is the result of my
desperation.  It translates a circuit file containing parameterized
subcircuits with math expressions into another circuit file meeting raw
spice requirements.  You then run spice on the translated output file.

This is an alpha version.  It probably has some bugs I haven't caught. 
But I have used it in a work environment enough to feel comfortable
about releasing it for comments and improvement suggestions.


What's So Great About Subcircuits With Parameters?
--------------------------------------------------
1.  You can generalize a model once and then use it without having to
recalculate values of it's internal elements every time.

2.  Many electronic devices can be modelled by using mathematical
expressions.  The independent variables can be passed to the model as
parameters, evaluated in equations, and used to set the behavior of a
particular model instance.

3.  They save mucho time and minimize human calculation error.


Installation
------------
1.  Copy the executable script to an accessible directory.  I keep mine
in $HOME/bin so it's on my path.

2.  Modify the top line if necessary to reflect the path to your Perl
interpreter.
For ex., #! /usr/bin/perl may have to become #! /usr/local/bin/perl or
wherever the perl binary is located.


Usage
-----
spiceprm infile [outfile]

    infile:     Circuit file name containing parameterized subcircuits.
    outfile:    Transformed file meeting raw spice netlist conventions.
                Optional.  If not given, output is produced on standard
                output (stdout).

    My file name convention:    infile = *.cir, outfile = *.ckt

    infile == outfile isn't permitted for a coupla good reasons, the
    best being you don't want to trash your original source.
    
Now source outfile from spice.

I always check the output from a new infile just to make sure.  This
version only checks for a few obvious errors, so scanning outfile for
reasonable looking values and netlist correctness is wise.  Note that
comment and blank lines are discarded in outfile and alphabetic
characters are transformed to lower case.


Parameterized Subcircuit Netlist Convention
-------------------------------------------
Calling a parameterized subcircuit works similarly to a normal spice call
except for the addition of a {} delimited list of parameter value
assignments -

Xname n1 n2 n3 ... ni subname {p1 = val1 ... pj = valj}
    p1 thru pj are the parameter assignments to be passed to the
        subcircuit.
    val is any valid spice value.
    {} (braces) must enclose the parameter assignment sequence.

After running the preprocessor on this file, each call in the netlist
will be replaced by the following -

Xname n1 n2 n3 ... ni subname#k
*{p1 = val1 ... pj = valj}
    where k is a digit or digits representing a subcircuit with that
    specific set of parameter substitutions.  k will be incremented for
    each unique set of parameters and matched by a new .subckt listing
    named subname#k as follows -

        .subckt subname#k n1 n2 n3 ... ni
        ... listing with parameters substituted and equations evaluated
        .ends


Creating Parameterized Subcircuits
----------------------------------
Below is a simple example.  See the EXAMPLES file for a number of
illustrative and useful models for Spice3.

This model creates an RF power source specified using the natural
output power units of dBm (dB referenced to 1 milliwatt).  Note that
the model parameters must be declared on the ".subckt" definition line
inside curly braces {}.
****************************************************************
* Sine wave RF power source.
* Parameters: F = Frequency
*             R = Output resistance
*             P = Power in dBm
*             V = DC (EMF)
.SUBCKT RFGEN 1 2 {F R P V}
*             + -
Is      2 1 DC {V/R} SIN {V/R} {sqrt((10**(P/10))/(125*R))} {F}
Ro      1 2 {R}
.ENDS
****************************************************************
Note that independent current source Is has it's literal spice
parameters replaced by equations that calculate the required values
from the passed parameters.  Each equation must be enclosed by {} to
inform the preprocessor that a substitution and calculation must be
performed for whatever appears between the braces.

Equations may span multiple lines by using the spice line continuation
symbol "+" as the first character of the following line.

.MODEL statements inside subcircuits may also use passed parameters. 
In fact, anything between {} inside a subcircuit will be evaluated and
replaced with a result.

Be careful in situations like the following:
    Bx 3 0 v = {v(1)*sgn(v(2))*frick/frack}     WRONG!!!
    
    The Spice3 nonlinear source element "B" also accepts equations
    describing it's output dependency on functions of circuit voltages
    and currents.  If "frick" and "frack" are parameters, you must
    separate them from the element's equation as follows -
        Bx 3 0 v = v(1)*sgn(v(2))*{frick/frack}

    Just remember that preprocessor equations and spice functions must
    never meld.

The parameter substitution first replaces all parameters between any {}
with their numerical values and then uses Perl's eval() function to
produce a final numerical value.  Theoretically at least,  you could
execute a Perl program within those braces.  I haven't explored this
yet so feel free.  Realize though, that whatever's inside the braces
gets a ";" appended at the end to make a valid Perl statement from the
usual equation.  Also, Perl's block delimiters are braces, so extra
one's could confuse the current parsing which is simply oriented to
equations.  Ah well.


Known Bugs, Anomalies, and Perl Gotcha's
----------------------------------------
1.  Minimal error checking!  Be forewarned!

2.  Don't use ".ends subckt_name" with parameters.  Use ".ends" only. 
The preprocessor modifies subckt_name to subckt_name#k.

3.  Spice unit representations like "k", "meg", etc, are not recognized
inside the {} equation sections of .subckt listings.  They may,
however, be used in the parameter assignment section of a .subckt call.

4.  "-" as part of .subckt name doesn't work but "_" does.  Stick to
alphanumeric names with optional underscore characters.

5.  Equations must use Perl math operators and functions.
    The following lists operator differences I'm aware of -

    Exponentiation -        Perl    : **
                            Spice3  : ^

    Logical AND, OR -       Perl    : &&, ||
                            Spice3  : &, |

    Equality, Inequality -  Perl    : ==, !=
                            Spice3  : =, <>

    These operators are the same for Perl and Spice3 -
    + - * / % ! < > <= >=

    These operators are unique to Perl -
    & | ^ ~     : bitwise AND, OR, exclusive OR, complement
    
    Perl math functions -
    abs(EXPR)   : absolute value of EXPR
    atan2(Y,X)  : arctangent of Y/X in the range of -pi to +pi
    cos(EXPR)   : cosine of EXPR in radians
    exp(EXPR)   : e raised to EXPR
    int(EXPR)   : integer portion of EXPR
    log(EXPR)   : natural logarithm (base e) of EXPR
    rand[(EXPR)]: returns a random fractional number between 0 and the
                    value of EXPR. If EXPR is omitted, returns a value
                    between 0 and 1.
    sin(EXPR)   : sine of EXPR in radians
    sqrt(EXPR)  : square root of EXPR


Finally, if you could make use of a language allowing you to do neat
things like this with minimal pain, give Perl a try.  It's naturally
suited for text processing and transformation tasks like pre and post
processors, along with any math manipulation required.
