››› Screenshot

THE SLIDE RULE OF SILICON DESIGN

Free Analog Circuit Simulation

Netlist Syntax

SpiceOpus, Berkeley SPICE and XSPICE

The original Berkeley netlist syntax for devices and models is kept throughout SpiceOpus except in the following cases:

  • XSPICE A devices and XSPICE .MODEL cards
  • Berkeley SPICE2 style POLY sources are supported, but not recommended. Use SPICE3 style B sources instead.
  • Many extensions have been made. To find out more, read this document.

Dividing a circuit netlist among multiple files (.include and .lib)

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:

.NETCLASS chiptype tm
.model nmosmod nmos LEVEL=... <typical mean model parameters>
.model pmosmod pmos LEVEL=... <typical mean model parameters>
.ENDN

.NETCLASS chiptype wo
.model nmosmod nmos LEVEL=... <worst one model parameters>
.model pmosmod pmos LEVEL=... <worst one model parameters>
.ENDN

.NETCLASS chiptype wz
.model nmosmod nmos LEVEL=... <worst zero model parameters>
.model pmosmod pmos LEVEL=... <worst zero model parameters>
.ENDN

.NETCLASS chiptype wp
.model nmosmod nmos LEVEL=... <worst power model parameters>
.model pmosmod pmos LEVEL=... <worst power model parameters>
.ENDN

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:

* Capacitor C1 normal operation
.NETCLASS criticalc normal
c1 1 2 10u
.ENDN

* Capacitor C1 shorted
.NETCLASS criticalc short
c1 1 2 10u
rc1p 1 2 1m
.ENDN

* Capacitor C1 open
.NETCLASS criticalc open
c1 1 int2 10u
rc1s int2 2 1G
.ENDN

* BJT Q1 normal operation
.NETCLASS criticalq normal
q1 10 20 30 q2n2222
.ENDN

* BJT Q1 open colector
.NETCLASS criticalq openc
q1 int10 20 30 q2n2222
rq1s int10 10 1G
.ENDN

* BJT Q1 shorted B-E
.NETCLASS criticalq shortbe
q1 10 20 30 q2n2222
rq1p 20 30 1m
.ENDN

Netclass and key enumeration, default netclasses

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.

Selecting a netclass key from Nutmeg

To select a particular key for a particular netclass, use:

netclass select <netclass name>::<key name>
* These three are also possible
netclass select <netclass number>::<key name>
netclass select <netclass name>::<key number>
netclass select <netclass number>::<key number>

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:

optimize analysis ...
optimize analysis 100 netclass uptodate reparse
optimize analysis 110 if reparse
optimize analysis 120 netclass rebuild
optimize analysis 130 optimize setparams
optimize analysis 140 end
optimize analysis 150 unlet reparse
optimize analysis ...

To reset all netclass keys to default keys (number zero keys), call:

netclass reset

Changes will again take effect after you call netclass rebuild. Some examples:

* Simulate normal operation for C1 and short B-E for Q1
netclass select criticalc::normal
netclass select criticalq::shortbe
netclass rebuild
* Simulation/analysis commands follow

* Simulate a short in C1 and short B-E for Q1
netclass select criticalc::short
netclass select criticalq::shortbe
netclass rebuild
* Simulation/analysis commands follow

* This is also possible
netclass select 0::1
netclass select 1::2
netclass rebuild

* To select worst one conditions for a chip simulation
netclass select chiptype::wo
netclass rebuild

Displaying netclasses

To display a list of all netclasses type:

listing nc

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:

.subckt attenuator in out comm
r1 in int 16.67 rmod1
r2 int out 16.67 rmod1
r3 int comm 66.67 rmod1
.model rmod1 r tc1=0.001 tc2=0.0001
.ends

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:

.subckt bigatten in out
xnested1 in int 0 attenuator
xnested2 int out 0 attenuator
.ends

To use subcircuit bigatten, insert the following line in the netlist:

xexample2 7 8 bigatten

The depth of nested subcircuits (like the one above) is not limited.

Subcircuit Name Expansion

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

Let's explain this using an exemplar circuit:

v1 int1 0 1
rin int1 1 50
xsub1 1 2 100 attenuator
xsub2 2 3 100 attenuator
xsub3 3 4 bigatten
rx1 100 0 1m
rout 4 0 50

This netlist expands to:

v1 int1 0 1
rin int1 1 50

This is the expansion of subcircuit instance xsub1 (attenuator):

r1:xsub1 1 int:xsub1 16.67 rmod1:xsub1
r2:xsub1 int:xsub1 2 16.67 rmod1:xsub1
r3:xsub1 int:xsub1 100 66.67 rmod1:xsub1
.model rmod1:xsub1 r tc1=0.001 tc2=0.0001

This is the expansion of subcircuit instance xsub2 (attenuator):

r1:xsub2 2 int:xsub2 16.67 rmod1:xsub2
r2:xsub2 int:xsub2 3 16.67 rmod1:xsub2
r3:xsub2 int:xsub2 100 66.67 rmod1:xsub2
.model rmod1:xsub2 r tc1=0.001 tc2=0.0001

And now the expansion of subcircuit instance xsub3 (bigatten). First the expansion of nested subcircuit xnested1 in xsub3 (attenuator):

r1:xnested1:xsub3 3 int:xnested1:xsub3 16.67 rmod1:xnested1:xsub3
r2:xnested1:xsub3 int:xnested1:xsub3 int:xsub3 16.67 rmod1:xnested1:xsub3
r3:xnested1:xsub3 int:xnested1:xsub3 0 66.67 rmod1:xnested1:xsub3
.model rmod1:xnested1:xsub3 r tc1=0.001 tc2=0.0001

The expansion of nested subcircuit xnested2 in xsub3 (attenuator):

r1:xnested2:xsub3 int:xsub3 int:xnested2:xsub3 16.67 rmod1:xnested2:xsub3
r2:xnested2:xsub3 int:xnested2:xsub3 4 16.67 rmod1:xnested2:xsub3
r3:xnested2:xsub3 int:xnested2:xsub3 0 66.67 rmod1:xnested2:xsub3
.model rmod1:xnested2:xsub3 r tc1=0.001 tc2=0.0001

And finally the last two resistances from the original netlist.

rx1 100 0 1m
rout 4 0 50

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.

Expansion rules

For node names:

node_name:lowest_level_full_subcircuit_instance_name:....

Example:

int:xnested1:xsub3

This means: node int inside subcircuit instance xnested1 that resides inside subcircuit instance xsub3.

For instance names:

full_device_instance_name:lowest_level_full_subcircuit_instance_name:....

Example:

r1:xnested1:xsub3

This means: resistor instance r1 (instance name 1) inside subcircuit instance xnested1 that resides inside subcircuit instance xsub3.

For model names:

model_name:lowest_level_full_subcircuit_instance_name:....

Example:

rmod1:xnested2:xsub3

This means: model named rmod1 inside subcircuit instance xnested2 that resides inside subcircuit instance xsub3.

Let's say you want to plot the voltage of internal subcircuit node int that resides inside subcircuit instance xnested1 that resides inside subcircuit instance xsub3. Simply type:

plot v(int:xnested1:xsub3)

To alter the resistance instance parameter to 20 for resistor r3 inside subcircuit instance xnested1 that resides inside subcircuit instance xsub3 type:

let @r3:xnested1:xsub3[resistance]=20

To alter the tc1 model parameter to 0.002 for model rmod1 inside subcircuit instance xnested1 that resides inside subcircuit instance xsub3 type:

let @@rmod1:xnested1:xsub3[tc1]=0.002

Global Nodes (.GLOBAL)

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...

Instance and node lookup for CMs, controlled sources (B, E, F, G, H, POLY) and K elements (v2.1)

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:

* K1 references instances (L1 and L2) inside the subcircuit (local instances)
.SUBCKT ...
...
K1 L1 L1 0.99
...
.ENDS

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:

.subckt subckt_name node1 node2 ...
+ noden [Param:] param1=def1 param2=def2 ... paramm=defm
subckt netlist
.ends

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:

* a is a real scalar
* b is a complex scalar
* c is a real vector
* d is a complex vector
* e is a parameter with no default value
.subckt demosub 1 2 3 Param: a=1 b=(1,2) c=(1;2;3) d=((1,2);(3,4)) e
...
.ends

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:

x1 conn1 conn2 ... connn subckt_name [Param:] param1=val1 param2=val2 ... paramm=valm

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:

* For b and d the default values are used
x1 10 20 30 demosub Param: a=10 c=2 e=1

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:

.subckt divider top out bottom Param: ratio=0.5 rtotal=10k
r1 top out {(1-ratio)*rtotal}
r2 out bottom {ratio*rtotal}
.ends

To instantiate a voltage divider with ratio 0.25 and total resistance 100k use:

x1 pow out 0 divider Param: ratio=0.25 rtotal=100k

One can also parametrize subcircuit instances inside a subcircuit definition:

.subckt bigsub top out1 out2 bottom Param: ratio1=0.25 ratio2=0.5 rtotal=100k
x1 top out1 bottom Param: ratio={ratio1/2} rtotal={rtotal}
x2 top out2 bottom Param: ratio={ratio2/2} rtotal={rtotal}
.ends

Curly braces can be ommited when passing expression values to subcircuit instances:

.subckt bigsub top out1 out2 bottom Param: ratio1=0.25 ratio2=0.5 rtotal=100k
x1 top out1 bottom Param: ratio=ratio1/2 rtotal=rtotal
x2 top out2 bottom Param: ratio=ratio2/2 rtotal=rtotal
.ends

Note that the latter is allowed with subcircuit instances only (not with SPICE devices). The following example is wrong:

.subckt divider top out bottom Param: ratio=0.5 rtotal=10k
r1 top out (1-ratio)*rtotal
r2 out bottom ratio*rtotal
.ends

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:

.subckt divider top out bottom Param: ratio=0.5 rtotal=10k tc=0
r1 top out {(1-ratio)*rtotal} rmod
r2 out bottom {ratio*rtotal} rmod
.model rmod r tc1={tc}
.ends

A B-source 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:

.subckt divider top out bottom Param: ratio=0.5 rtotal=10k tc=0
.param r1=(ratio-1)*rtotal
.param r2=ratio*rtotal
r1 top out {r1} rmod
r2 out bottom {r2} rmod
.model rmod r tc1={tc}
.ends

This is also possible (results in the same subcircuit as the previous definition):

.subckt divider top out bottom Param: ratio=0.5 rtotal=10k tc=0
.param r2=ratio*rtotal
* A previously defined parameter is used in the expression
.param r1=rtotal-r2
r1 top out {r1} rmod
r2 out bottom {r2} rmod
.model rmod r tc1={tc}
.ends

Avoid recursion when using .PARAM:

* This should be avoided
.subckt 1 2 rhalved Param: a
.param a=a/2
r1 1 2 {a}
.ends

* This is better
.subckt 1 2 rhalved Param: a
.param tmpa=a/2
r1 1 2 {tmpa}
.ends

.PARAM defines a global parameter if it is used outside a subcircuit definition. A global parameter is accessible in all parametrized expressions inside or outside subcircuit definitions.

* Define some globals
.param con1=2
.subckt 1 2 rhalved Param: a
.param tmpa=a/con1
r1 1 2 {tmpa}
.ends
* Global parameters can also be used in the top level circuit
* 5k resistor
rtop 1 0 {10k/con1}
* This is also legal, 10k is passed as the value of a
x1 5 0 rhalved Param: a=20k/con1

If a subcircuit parameter with the same name as the global parameter is defined, the local parameter value is used. The global parameter is left unchanged:

* Define some globals
.param con1=2
.subckt 1 2 rhalved1 Param: a
.param con1=3
* 3 is used for con1 inside rhalved1, global con1 value is left unchanged
.param tmpa=a/con1
r1 1 2 {tmpa}
.ends
* con1 is global here (2 is used, resulting in 5k)
r1 9 0 {10k/con1}

* Another example
.param con1=5
* con1 inside rhalved2 is also local.
* This time it is passed as a parameter to rhalved2 with 2 for default).
.subckt 1 2 rhalved2 Param: a con1=2
.param tmpa=a/con1
r1 1 2 {tmpa}
.ends
* con1 is global here (5 is used, resulting in 4k)
r1 9 0 {20k/con1}

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:

* Define some globals (con1 = 6.28...)
* pi is found in the const plot
.param con1=2*pi
* Default for a is 5k/pi
* No curly braces are used for default expression!
.subckt 1 2 rfac Param: a=10k/con1
.param tmpa=a/con1
r1 1 2 {tmpa}
.ends

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 real scalar
.param rscal=9
* A complex scalar
.param cscal=(1,9)
* A real vector (1.0;2.0)
.param rvec=(1;2)
* A complex vector ((1,0);(1,2))
* Note that (1,0)==1
.param cvec=(1;(1,2))
* Now let's see how this works in a SPICE device/model

V1 1 2 0 PULSE {rscal} 2 0.1m 1u 1u
* ^^^^ expands to: V1 1 2 0 PULSE 9 2 0.1m 1u 1u
* {rscal} expands to '9'

V2 2 3 0 PULSE {cscal} 0.1m 1u 1u
* ^^^^ expands to: V2 2 3 0 PULSE 1 9 0.1m 1u 1u
* {cscal} expands to '1 9'

V3 4 5 0 PULSE {rvec} 0.1m 1u 1u
* ^^^^ expands to: V3 4 5 0 PULSE 1 2 0.1m 1u 1u
* {rvec} expands to '1 2'

V4 5 6 0 PULSE {cvec} 10 10
* ^^^^ expands to: V4 5 6 0 PULSE 1 0 1 2 10 10
* {cvec} expands to '1 0 1 2'

To summarize the rules for expressions in built-in SPICE models:

{real scalar} -> value
{complex scalar} -> rvalue ivalue
{real vector} -> value1 value2 ...
{complex vector} -> rvalue1 ivalue1 rvalue2 ivalue2 ...

The rules for XSPICE code models are somewhat different (different syntax):

{real scalar} -> value
{complex scalar} -> <rvalue,ivalue>
{real vector} -> [value1 value2 ... ]
{complex vector} -> {< rvalue1 ivalue1 > < rvalue2 ivalue2 > ... ]

Example:

.param rvec=(1;1;0)
.model cm1 some_code_model real_vector={rvec}
* ^^^^ expands to: .model cm1 some_code_model real_vector=[1 1 0]
* {rvec} expands to '[1 1 0]'

Remember. No type checking is done so in case you specify an expression that results in a vector where one should use a scalar, the parser will report an error and refuse to parse the circuit.

Listing The Circuit, Global Nodes, Subcircuit Definitions And Subcircuit Instances (v2.1)

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 cannot define a subcircuit inside a subcircuit definition). Consider the following netlist:

TESTNET

.param testp1=100
.param testp2=testp1*9
* Complex vector (1,0);(2,0);(3,1)
.param vec1=(1;2;(3,1))
* Real vector 1;2;3
.param vec2=(1;2;3)

.global vss vdd

.subckt test1 1 2 3
r1 1 2 1
r2 2 3 1
.ends

.subckt test 1 2 3 param: a=5*testp2 b c=vec1 d=9 e f=vec2 g
.param hello = 1
.param aw = 2
.param u=5
r1 1 2 1
r2 2 3 1
.ends

xtestsub 50 60 0 test param: b=1 e=vec1 d=1 g=1

.subckt tcres n1 n2 param: r tc1=0 tc2=0 temp=27 tnom=27
r1 n1 n2 {r} rm temp={temp}
.model rm r tc1={tc1} tc2={tc2} tnom={tnom}
.ends

.subckt vdiv up down out param: k=0.5 r=1k
.param upr=r*(1-k)
.param dnr=r*k
.param tclin=0.01
x1 up out tcres param: r=upr tc1=tclin
x2 out down tcres param: r=dnr tc1=tclin*2
.ends

xdiv 1 0 out vdiv param: k=0.25 r={10k*testp1}

rtop 10 0 1

.control
echo hello
.endc

.end

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:

SpiceOpus (c) 21 -> listing subdef
Active subcircuit definitions:
vdiv
tcres
test
test1
topdef_
----

topdef_ is the top level circuit definition.

listing subdef name1 name2 ...

Displays the information on listed subcircuit definitions. Example:

SpiceOpus (c) 24 -> listing subdef topdef_ tcres vdiv
Instances of topdef_ :
xtopinst_

Definition of topdef_ :
Terminals:
--none--
Parameters:
--none--
Parametric expressions:
testp1 = 100
testp2 = testp1*9
vec1 = (1;2;(3,1))
vec2 = (1;2;3)
Elements:
xtestsub 50 60 0 test param: b=1 e=vec1 d=1 g=1
xdiv 1 0 out vdiv param: k=0.25 r={10k*testp1}
rtop 10 0 1
----
Instances of tcres :
x2:xdiv
x1:xdiv

Definition of tcres :
Terminals:
n1 n2
Parameters:
r
tc1 = 0
tc2 = 0
temp = 27
tnom = 27
Parametric expressions:
--none--
Elements:
r1 n1 n2 {r} rm temp={temp}
.model rm r tc1={tc1} tc2={tc2} tnom={tnom}
Instances of vdiv :
xdiv

Definition of vdiv :
Terminals:
up down out
Parameters:
k = 0.5
r = 1000
Parametric expressions:
upr = r*(1-k)
dnr = r*k
tclin = 0.01
Elements:
x1 up out tcres param: r=upr tc1=tclin
x2 out down tcres param: r=dnr tc1=tclin*2
----

For every subcircuit definition the list of instances is printed along with the terminals, parameters, default values, parametric expressions (.PARAM clauses) and list of elements.

listing sub

Displays the list of all instances sorted by their respective subcircuit definitions. Example:

SpiceOpus (c) 25 -> listing sub
Subcircuit instances of vdiv:
xdiv

Subcircuit instances of tcres:
x2:xdiv
x1:xdiv

Subcircuit instances of test:
xtestsub

Subcircuit instances of test1:
--none--

Subcircuit instances of topdef_:
xtopinst_

listing sub name1 name2 ...

Displays information on listed subcircuit instances. Example:

SpiceOpus (c) 31 -> listing sub xtopinst_ xtestsub xdiv x2:xdiv

Subcircuit instance xtopinst_ :
Definition : topdef_
Instantiated in top level circuit
Connections (model -> instance) :
--none--
Parameters :
--none--
----

Subcircuit instance xtestsub :
Definition : test
Instantiated in top level circuit
Connections (model -> instance) :
1 -> 50
2 -> 60
3 -> 0
Parameters :
a = (dfl) 4500
b = 1
c = (dfl) ((1,0);(2,0);(3,1))
d = 1
e = ((1,0);(2,0);(3,1))
f = (dfl) (1;2;3)
g = 1
----

Subcircuit instance xdiv :
Definition : vdiv
Instantiated in top level circuit
Connections (model -> instance) :
up -> 1
down -> 0
out -> out
Parameters :
k = 0.25
r = 1e+006
----

Subcircuit instance x2:xdiv :
Definition : tcres
Instantiated in xdiv
Connections (model -> instance) :
n1 -> out
n2 -> 0
Parameters :
r = 250000
tc1 = 0.02
tc2 = (dfl) 0
temp = (dfl) 27
tnom = (dfl) 27
----

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:

@xname[parameter]

Examples:

* Prints the a parameter for subcircuit instance x1:xamp1
print @x1:xamp1[a]

* 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.

The .MPARAM Clause (v3.0)

Syntax:

.MPARAM parameter [=expression]

Another way to define subcircuit parameters is to use the .MPARAM clause. Suppose you define a voltage divider subcircuit in the usual way:

.subckt divider top out bottom Param: ratio=0.5 rtotal=10k tc
.param r1=(ratio-1)*rtotal
.param r2=ratio*rtotal
r1 top out {r1} rmod
r2 out bottom {r2} rmod
.model rmod r tc1={tc}
.ends

The same can also be achieved with .MPARAM:

.subckt divider top out bottom
.mparam ratio=0.5
.mparam rtotal=10k
.mparam tc
.param r1=rtotal-r2
.param r2=ratio*rtotal
r1 top out {r1} rmod
r2 out bottom {r2} rmod
.model rmod r tc1={tc}
.ends

Note how we did not specify the default value in the last .MPARAM clause. .MPARAM can be used for adding modifiable parameters to the toplevel subcircuit definition. A global parameter defined with .MPARAM can be modified via the toplevel subcircuit definition (topdef_) or toplevel subcircuit instance (xtopinst_). Because there is only one toplevel subcircuit instance both are equivalent. Suppose we have the following netlist.

Using .mparam to define modifiable global parameters
.mparam top1=10
.mparam top2=20
r1 (1 2) r={r1}
r2 (2 3) r={r2}
.end

Now let us change parameter top1 via xtopinst_ instance (in prompt or .control block)

let @xtopinst_[top1]=30

Because there is only one toplevel subcircuit instance the same result would be obtained with

let @@topdef_[top1]=30

Every time you assign a value to a toplevel parameter the whole circuit is reparsed. The following code can be quite expensive because it will reparse the whole circuit 4 times.

let @@topdef_[top1]=30
let @@topdef_[top2]=40
let @@topdef_[top1]=50
let @@topdef_[top2]=60

It is much cheaper to turn off automatic reparsing and reparse the toplevel circuit manually after all changes have been made.

set manualscktreparse
let @@topdef_[top1]=30
let @@topdef_[top2]=40
let @@topdef_[top1]=50
let @@topdef_[top2]=60
scktreparse xtopinst_

This time the circuit will be reparsed only once. Manual subcircuit reparsing is in effect until you unsetup the manualsubcktreparse variable.

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):

...
m1 drain gate source bulk nmod l=4um w=120um ...
...
.model nmod_1 nmos level=5x lmin=1u lmax=5u wmin=1u wmax=100u ...
.model nmod_2 nmos level=5x lmin=5u lmax=10u wmin=1u wmax=100u ...
.model nmod_3 nmos level=5x lmin=1u lmax=5u wmin=100u wmax=250u ...
.model nmod_4 nmos level=5x lmin=5u lmax=10u wmin=100u wmax=250u ...
...

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):

m1 drain gate source bulk nmod_1 l=4um w=120um ...
...
.model nmod_1 nmos level=5x lmin=1u lmax=5u wmin=1u wmax=100u ...
.model nmod_2 nmos level=5x lmin=5u lmax=10u wmin=1u wmax=100u ...
.model nmod_3 nmos level=5x lmin=1u lmax=5u wmin=100u wmax=250u ...
.model nmod_4 nmos level=5x lmin=5u lmax=10u wmin=100u wmax=250u ...
...

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.