In many cases it is practical to divide a large netlist among multiple files. SpiceOpus provides two means for
accomplishning this: .include and .lib netlist directives. Both of them are preprocessor directvies
and include an external file or a part of an external file in the netlist that is parsed. .include and .lib
can be used throughout the whole netlist (not just outside, but inside .SUBCKT and .CONTROL blocks also).
Note that these are preprocessor directives and merely include a text from other files.

.include

Syntax:

.include filename

or

.include path/filename

Includes a file.

.lib

Syntax:

.lib 'filename' section

or

.lib 'path/filename' section

Includes a file section. A file section can be specified in the following manner:

.lib section
...
* stuff to include
...
.ENDL

Both .include and .lib can go as deep as you want. Recursion is not allowed and in case it happens an
error message is produced when a netlist is being loaded. Don't forget to surround the filename with single
quotes. Use '/' as the path separator in Windows and in Unix although '\' also works for Windows.

How SpiceOpus searches for .include and .lib files?

In case the file is specified with its full or partial path, use '/' instead of '\' in Windows. This will make your
netlists more portable. In case you use '/' in Windows they will get converted to '\' automatically. For specifying a
drive in Windows use the same syntax as in Dos (e.g. 'c:'). We recommend against using a drive specification since this
makes you netlists less portable to Unix.

A file is first searched in the current directory if it is specified as a filename. If you specify a relative
path, the first path tried is relative to the current directory. To see the current working directory, use the Nutmeg command:

echo $(workdir)

or

cd .

To change to your home directory (Unix only) type:

cd

To change your working directory type:

cd directory

If the file is not found it is looked up relative to the directories specified in the sourcepath variable.
To set the sourcepath type (usually in the spinit file):

* This will add path1, ... to the sourcepath
set sourcepath=( $(sourcepath) path1 path2 ... )
* This will set sourcepath to path1, ...
set sourcepath=( path1 path2 ... )
* Don't forget to add a space after '(' and before ')'.

Default sourcepath is set to:

. <lib/scripts directory>

This means that the files are looked up in the current directory and in then in the lib/scripts directory
where SpiceOpus is installed. Finally if the file is still not found, the file is looked up relative to the directory
where the file, from where the .include or .lib call was made, resides.

Netclasses (.netclass) (v2.1)

In many cases one requires multiple different descriptions for the same part of the circuit.
One such case is the cornerpoint analysis in chip design where designers have different models
for different extreme conditions that can occur at chip fabrication (like typical mean, worst
one, worst zero,worst power, etc.).

Another use is in failure mode analysis (FMA) where a circuit (usually comprising
discrete components) is simulated for various failure modes (e.g. Q1 short between C and
B, Q1 short between B and E, Q1 open at C, ...).

Defining a netclass (.NETCLASS, .ENDN)

To define a section of netlist that describes a particular operating condition use:

.NETCLASS classname classkey
...
condition description
...
.ENDN

Using .NETCLASS for defining corner points

Let's define 4 netclasses from class chiptype and name them tm, wo, wz and wp. Each of them will
describe the respective NMOS and PMOS models:

Chip fabrication facilities usually provide designers with such models for
NMOS, PMOS, diffusions, etc. Of course you don't have to copy .MODEL cards from other files.
You can simply .include or .lib them into a .NETCLASS block.

Using .NETCLASS for defining failure modes

Let's define 6 netclasses, 3 from the class criticalc and 3 from the class criticalq:

Netclass names are automatically enumerated in the same order as they are found in the netlist,
starting from 0. Keys for a particular netclass are also automatically enumerated in the same
order as they are found in the netlist starting from 0. In the above described case of failure
modes, the enumeration is as follows:

criticalc 0
normal 0
short 1
open 2

criticalq 1
normal 0
openc 1
shortbe 2

Default key for every netclass is the one enumerated with 0. This is the key that is first
defined for a particular netclass. It is recommended to define as the first key the normal
operating conditions. In case multiple .NETCLASS blocks with the same netclass name and key name are defined
they are treated as members of the same netclass::key combination. The default netclass key is the one
that is active when the control block is started. If you would simulate the FMA example described above
the normal key would be used for the criticalc netclass and the normal key would be used for the criticalq
netclass. In fact you would simulate normal operating conditions for C1 and Q1.

Changes in active keys, if there are any, will take effect after you call:

netclass rebuild

If there were no changes (active keys are the same as currently parsed ones) then netclass rebuild
command will be ignored and circuit not reparsed. To force reparsing regardless key matching use
forcerebuild variable. If the variable is set then reparsing is always performed. The information about
key matching can also be retrieved by:

netclass uptodate <scalar>

Value of scalar is set to one if circuit update is needed. That means that active keys are
not the same as currently parsed ones and circuit reparsing or rebuilding should take place.
Otherwise is set to zero and circuit update is not needed. Circuit reparsing will also
reset all instance parameter values to the ones specified in active netclass descriptions. In
case you call a netclass rebuild this during an optimize analysis and the command is not ignored,
call also:

optimize setparams

The command properly set all instance parameters mathematically linked to optimisation
parameters with let commands. Example:

This lists all netclasses and all keys. It also marks the active keys and
warns you if the netlists needs a netclass rebuild. To display a list of active
netclass keys for all netclasses type:

listing activenc

To get information on selected netclasses type:

listing nc netclass1 netclass2 ...

In case the circuit needs a netclass rebuild (active keys have changed
since the last netclass rebuild call), a waring is printed.

Important Note Regarding Name Expansion In Subcircuits

SpiceOpus uses the XSPICE style subcircuit name expansion (which is more logical than
Berkeley style). Nutmeg scripts that access elements/models in subcircuits won't work
if they are written for the Berkeley SPICE.
Read the sections below to learn more about XSPICE style of subcircuit name expansion.

A Quick Guide To Subcircuits

A subcircuit can be declared using the following syntax:

.subckt subckt_name node1 node2 node3 ...
subckt netlist
.ends

Nodes node1, node2, ... are the interface to the outside world. Node 0 inside a subcircuit
has the same meaning as everywhere else in the circuit (ground node). A subcircuit can
be used in your netlist:

x1 node1 node2 node3 ... subckt_name

The above statement puts subcircuit named subckt_name as subcircuit instance x1 in your circuit
and connects it to nodes node1, node2, node3, ... Let's take a look at an example:

The subcircuit defined above is a 6dB attenuator with temperature dependence caused
by the temperature dependence of resistors (see resistor model rmod1). Model rmod1, devices
r1, r2 and r3 and node names in, out, comm and int are valid only inside this subcircuit.
You can reuse these names somewhere else in the netlist without worrying about name conflicts.
In order to use this subcircuit in a netlist the x element must be used:

xexample1 6 7 0 attenuator

This places subcircuit attenuator as subcircuit instance xexample1 in your circuit and connects
nodes in, out and comm of the subcircuit to nodes 6, 7 and 0 of the circuit. Subcircuits can be
used also in higher level subcircuits. As an example let's build a 12dB attenuator from
two 6dB attenuators:

In order to refer to internal nodes, devices and models inside subcircuits you must know
how the names are expanded before the netlist is parsed. What is subcircuit expansion?
Before SPICE actually parses the circuit, it makes two passes through the netlist. During
the first pass subcircuit definitions are collected. During second pass SPICE actually
replaces each subcircuit reference ('x' element) with the actual subcircuit. This is not
as trivial as it may seem. Generally two things need to be done:

Replace subcircuit nodes that represent its interface with the nodes specified in
the subcircuit instance call (X line).

Rename all internal subcircuit nodes, devices and models so name conflicts can't occur.
Subsequently all references to these nodes, devices and models inside the
subcircuit must also be renamed

Full instance name consists of a device letter and the rest of the instance name. An example
is rin10: r is the device letter telling the parser that it is dealing with a resistor and in10
is the rest of the instance name. Another example is xinner1: x is the device letter that tells
the parser it is dealing with a subcircuit and inner1 is the rest of the subcircuit instance name.

In version 2.02 .global HSPICE option was introduced. This option makes certain nodes global thus
preventing their expansion when they are found in subcircuits. Ground node (0) is global by default.
To make nodes global, enter the following option in your netlist:

.global node1 [node2 [node3 ...]]

To make nodes vdd and vss global enter the following option in your netlist:

.global vss vdd

Now all nodes named vdd and vss are no longer expanded when they are inside subcircuits.
This enables you to make connections to subcircuits without stating any connection interface nodes
in a subcircuit definition. In a sense this is similar to global variables in C.

Local and global .model definitions (v2.1)

A model defined inside a subcircuit is a local model. Such a model can only be accessed inside that subcircuit.
A model defined outside a subcircuit is a global model. Such a model can be accessed in the top level circuit
and in all subcircuit. If a local model has the same name as the global model, the local model is used.
Smells like C...

In case any of the above mentioned netlist elements or models is used inside a subcircuit definition
all instance names are expanded. This makes all references of other instances inside a subcircuit
definition local:

Same goes for nodes. Node names are also expanded and translated which makes them local unless
they appear in the subcircuit connection list or they are global. A subcircuit connection is the
only way beside global nodes to send a signal into a subcircuit.

Parametrized Subcircuits (v2.1)

A subcircuit can be parametrized by defining it in the following manner:

Where defi is the default value for parameter parami. The default value can be ommited.
In the latter case the parameter value must be specified at the subcircuit instantiation.
Default values can be real or complex scalars or vectors. The syntax is the same as in Nutmeg.
Example:

The Param: keyword can be ommited. In case it is ommited, the first parameter
(param1) must have a default value otherwise it will be interpreted as one of the
connection nodes of the subcircuit. In case the Param: keyword, parameter names and their
defaults are ommited the subcircuit is parameterless and acts like an ordinary SPICE
subcircuit. A parametrized subcircuit can be instantiated in your netlist in the
following manner:

The Param: keyword can be ommited. The parameter along with its value can be ommited. If a parameter
is not specified at instantiation, the default value is used. If no default value is found,
an error occurs. Example:

In case the Param: keyword, parameters and their values are ommited, the default values are used
for all parameters. If any default is missing at subcircuit definition an error occurs. To parametrize
an instance or model parameter value use the {expression} syntax. Let's define a voltage divider
with a variable ratio:

In case curly braces are ommited, use the 'eq' operator instead of '='. Any valid Nutmeg operator, function
or constant from the const plot can be used in an expression. Avoid using the '=' operator since it causes
problems in some special cases. Use 'eq' instead. Models can also be parametrized:

* A multiplier
.subckt mult in1 in2 out Param: offset=0 factor=1
B1 out 0 V=({offset})+({factor})*v(in1)*v(in2)
.ends
* Another example
* A sigmoid transfer function
.subckt sigmoid in out Param: offset=0 span=2 steepness=1
* Note that constant PI is taken form the const plot because {pi} is used
B1 out 0 V=({offset})+({span/pi})*atan(v(in))*({pi/2*steepness}))
.ends

Note that {} expressions are surrounded by a second set of ordinary brackets (). This prevents errors if
an {} expression expands to a negative number.

The .PARAM Clause (v2.1)

Syntax:

.PARAM parameter=expression

Additional parameters can be defined using the .PARAM clause. These parameters are
evaluated after the parameters are passed to the subcircuit but prior to any element or
model instantiations. It doesn't matter where in the subcircuit definition the .PARAM clause
is located. It is always evaluated prior to any instance/model parsing. .PARAM clauses
are evaluated in the same order as they are found in the subcircuit definition.
Example:

Yes, default value can also be specified as an expression. Remember not to put curly braces
around the expression! A global parameter can be used in an expression as long as the global
parameter is defined before the subcircuit definition:

This is legal too. Don't use curly braces for the default value expression:

* No curly braces are used for default expression!
* a defaults to 5k
.subckt 1 2 rfac Param: a=10k/2

Parameter Expansion (v2.1)

Parametrized subcircuits work by means of parameter expansion. The trick is that for the built-in
SPICE devices and XSPICE CMs the value of the expression in the curly braces gets converted
to the format required by the respective device/model line. All parameters are Nutmeg vectors which
means they can be real or complex with an arbitrary number of components. No type checking is
performed. You have to make sure that the line makes sense (e.g. the result of an expression
must be a real scalar for a real scalar device/model parameter). Let's take a look at an example
which clarifies this:

A circuit consists of modules (subcircuit instances). One module is always present. That is the
top level circuit (named xtopinst_). Its definition is named topdef_. There is always only one
xtopinst_ module. The top level circuit and other modules may comprise multiple sub-modules (sub circuit
instances). Modules (subcircuit instances) can be nested. Definitions cannot be nested (i.e. one c
annot define a subcircuit inside a subcircuit definition).
Consider the following netlist:

The top level circuit (xtopinst_) consists of resistor instance rtop and modules xdiv and
xtestsub. The definition of xtopinst_ is topdef_. The definition of xdiv is vdiv and the definition
of xtestsub is test. xdiv comprises modules x1:xdiv and x2:xdiv. The definition of x1:xdiv and x2:xdiv
is tcres. x1:xdiv and x2:xdiv both consist of a resistor instance (r1:x1:xdiv, r1:x2:xdiv) and a
resistor model (rmod:x1:xdiv, rmod:x2:xdiv). The following commands are available for getting
information on the active circuit's netlist:

listing

or

listing logical

The latter two commands display the netlist along with line numbers. The .control block is ommited.

listing physical

Displays the physical listing (all lines from input file(s) including the .control block
and empty lines) with line numbers.

listing deck

Same as previous except that line numbers are ommited.

listing global

Displays all global nodes. For the TESTNET netlist the result is:

SpiceOpus (c) 19 -> listing global
Global nodes: vss vdd

listing subdef

Displays a list of all subcircuit definitions. For the TESTNET listing it displays:

For each instance the name of the definition is printed along with the place where it is
instantiated, connections and parameters. If a parameter is set to the default (ommited at
subcircuit call) (dfl) is printed in front of the value.
There is always one top level subcircuit (topdef_) instance named xtopinst_.

Altering/reading subcircuit parameters from Nutmeg (v2.1)

To access a subcircuit parameter from Nutmeg use the following syntax:

* Sets the a parameter for subcircuit instance x1:xamp1 to 10
let @x1:xamp1[a]=10

All instances/models/subcircuits in the subcircuit instance for which the parameter is
altered are reparsed and affected parameters recalculated.
To alter a particular parameter for all instances of some subcircuit use

@@submod[a]

This way you can alter parameter a for all instances of subcircuit submod. Parameter
a must be given a default value in the subcircuit definition. Examples:

* Prints the default value of the a parameter for subcircuit definition ampmod
print @@ampmod[a]

* Sets the a parameter to 10 for all subcircuit instances of ampmod
let @@ampmod[a]=10

All instances/models/subcircuits in the subcircuit instance for which the parameter is
altered are reparsed and affected parameters recalculated.

Automatic model selection (binning) for BSIM3v3 MOSFET device model

BSIM3v3 and BSIM4 MOSFET (level = 53 and 54) device models are usually valid only for a
specified range of transistor channel widths and lengths. Valid range is given by lmin,
lmax, wmin and wmax model parameters and instance's width and length are given by its w
and l parameters. Consequently relations lmin < l < lmax and wmin < w < wmax should
hold. In general if channel is changed outside specified w,l range another model covering
new dimensions should be selected. To get continuous passages on borders between different
width and length ranges binning technique is used (defined by binning model parameters).
Model names have the following syntax:

<model_name>_<bin_name>

bin_name can be omitted in transistor instance line. SpiceOpus searches among models with
the same model name and different bin names. The right model will be automatically selected.
Example (level = 53 or 54):

In the above example model mod_3 will be selected for instance m1.
If wrong bin_name is given in the transistor instance line then the right bin will
be automatically selected. Example (level = 53 or 54):

In the above example model mod_3 will be selected for instance m1, regardless
that mod_1 was specified. If instance's channel width and length do not fit into any of
the specified model bins, then the nearest bin will be selected.