6.1 Using the model compiler
This section is a first cut at documentation. If you actually want to
install a model, please ask for more information. Your questions will
help me write the more complete documentation. (aldavis@ieee.org)
To create a model using this method, you create one file, with the
extension .model. A separate program, modelgen processes
this file to generate the appropriate .cc and .h files.
The resulting files are equivalent to the subcircuit method of
creating models.
There are two primary sections, device and model. Most
models have both, but a device can use several different models
as long as they are derived from a common base and designed to work
together. It is standard practice to share like this. For example,
all of the MOS models use the same device section.
Any model can inherit from another model, thus reducing
the need for repetition when code or parameters are the same in
different models, and allowing several to use the same device
section.
This model compiler has restrictions that will be removed in future
releases. Not all device types can be fully done with it, due to
missing features. Often, it is necessary to finish the job manually.
In this release (0.30), the diode fully uses it, but not the way I
want to. The MOSFET uses the cc_direct to finish the job. Two
functions do_tr and tr_needs_eval must be provided this
way. Code placed here is simply copied out.
As a general rule, when using the name = value form, the value is
delimited by whitespace, or possibly other tokens. If you want blanks
in the value string, put it in quotes. It is recommended to quote any
value string that is comprised of more than one word, even if there
are no blanks.
6.1.1 Device section
- parse_name
- (required)
This is the name of the device, to be recognized by the parser, in
Gnucap native format. Example: diode.
- id_letter
- (required)
This is the letter used to identify the device, when the parse_name is omitted (Spice format). Example: D identifies a
diode.
- model_type
- (required)
This is the name of the model type associated with this device type.
It can be the name of the one matching type, or the name of a base
from which a family can be derived.
- circuit
- (required)
This is a subsection containing a netlist representing the internal
structure of the device. See the section circuit subsection for
details.
- tr_probe
- (optional)
This is a subsection containing a list of internal probes to be made
available to the user. See the section Tr_probe subsection for
details.
- device
- (required)
This is a subsection describing the non-shared data relating to the
device. Information here is unique to this device. It is primarily
state information. See the section Device subsection for
details.
- common
- (optional)
This is a subsection describing the shared data relating to the device.
Information here may be shared between similar devices. It is
primarily information that is read from the circuit description. See
the section Common subsection for details.
- tr_eval
- (optional)
This is a subsection which will eventually contain evaluation code for
the whole device. For now, it is a stub, which is used as a flag.
See the section Tr_eval subsection for details. If this
subsection is omitted, it is considered to be a pure subcircuit.
- eval
- (optional)
There may be any number of eval subsections, which are specific
evaluators for internal elements. See the section Evaluators
for details.
Circuit subsection
The circuit subsection has 5 parts, in order.
- The optional keyword “sync” says that the entire subcircuit
representing the device must be evaluated synchronously. Without this
keyword, it is treated as a subcircuit made of independent elements.
- The port list “ports”, which is a list of the nodes
interfacing to the outside.
- A list of local internal nodes, not visible outside.
Each local node may have two optional attributes:
- short_if
-
This specifies a conditional which if true will result in this node
being omitted.
- short_to
-
This specifies another node which will be substituted for this node if
the short_if condition is true.
- Any number of named and typed args sections. Each section
contains name = value pairs which assign values to elements in the
subcircuit. It is used only for more complex elements like diodes.
- A list of circuit elements that comprise the model. Each has three
required fields, then a list of optional key = value pairs.
The required fields, in order, are:
- The type of element. This is usually one of resistance, capacitance,
admittance, or poly_g, but can be any device type, including those
created by modelgen.
- The label, a string used to refer to it.
- A node list, in curly braces.
After that, optional fields are used to assign attributes. Not all
are legal or appropriate with all element types.
- value
-
This must evaluate to a constant, which is interpreted as the nominal
value of the element.
- eval
-
This is the name of an eval section, which specifies nonlinear,
and depenndent characteristics.
- args
-
This refers to an args section, described previously. It is
used only for advanced element types, as those created by modelgen.
- reverse
-
This specifies an expression, that when evaluated will tell whether to
reverse the element. If it evaluates to true, the node pairs are
interchanged. If there are two nodes, they are interchanged. If
there are four, the first pair are interchanged and the second pair
are interchanges. The pattern repeats for as many nodes as there are.
This is used with diodes, which may be reversed depending on whether
the device being defined is N-type or P-type.
- omit
-
This specifies an expression, that when evaluated will tell whether to
omit the element. If it evaluates to true, the element is omitted.
- state
-
This specifies a the name of a device state variable that is applied
to this element. This state variable must be one of those defined
under calculated parameters. It is primarily intended for the
poly_g and poly_cap element types. In the calculated
parameters section, the following parameters are its derivatives. If
the poly element has N node pairs, the following N parameters are the
derivatives, with respect to each voltage, in order.
Tr_probe subsection
The tr_probe subsection is where you list the probes for
transient and DC analysis. It is a list of name = value pairs, where
the value is an expression that calculates or looks up the value.
You can reference any device parameter directly, or others with the
appropriate struct prefixing.
You can reference probes on internal elements with the syntax “@”, followed by the element label, followed by the probe name in
square brackets. For example, “@Cj[Capacitance]” refers to
the probe named “Capacitance” on the element “Cj”. It is your
responsibility to see that the element actually exists, and that it
has a probe with that name.
You can reference node voltages with the same syntax, but the
“device” name is formed by prefixing the node name with “n_”.
You can also call functions, and make arbitrary expressions. In
general, the code is just copied over, with the exception of the
probes, which are modified to the internal format.
The probe name in the generated model will be non-case-sensitive. To
the model compiler, upper case letters must match exactly, and lower
case letters are optional. For example, “CGSOvl” in the model
file can be referred to as cgso, cgsov, or cgsovl,
or any variants differing only in case.
Device subsection
This subsection defines information that is not shared between
instances. In general, that which must be maintained as different,
even though devices are identical, is placed here.
Calculated_parameters subsubsection
This subsubsection lists all of the “calculated parameters”. In
this case, it means that which is calculated during simulation, the
state information.
The format for each item is: type, name, comment, attributes, semicolon.
The only attribute appropriate is “default”, which is the
default value set by the constructor.
Common subsection
This section defines information that the simulator may share between
instances. Most parameters specified by the user are placed here,
allowing the simulator to share data for identical devices.
Unnamed subsubsection
You can designate one of the raw_parameters to be the
“value”. When a number is given without a name, it is assigned to
this one.
Raw_parameters subsubsection
This subsubsection lists all of the “raw parameters”, the parameters
supplied by the user on the instance line. The format and available
attributes are described in the “Parameter lists” section, which
follows.
Calculated_parameters subsubsection
This subsubsection lists all of the “calculated parameters”, the
parameters not supplied by the user on the instance line. Instead,
the are calculated based on other input. The format and available
attributes are described in the “Parameter lists” section, which
follows.
Tr_eval subsection
In this release, this section is a dummy. Put a stub here if you
define a do_tr later. Otherwise leave it out. This will change
in a future release.
Evaluators
The eval sections are evaluators that turn the primitive
resistors and capacitors into advanced behavioral elements.
The body is the core of a C++ function, which is copied over directly
after attaching some headers. Given some “x”, this function
computes “f(x)” and its derivative with respect to x. The primary
communication is through the structure “d->_y0”. The input is
“d->_y0.x”. You must evaluate the function, and place the
result in “d->_y0.f0” and its derivative in “d->_y0.f1”. The exact meaning of these values depends on what type
of element it is.
For the primitives ...
- resistance
-
x is current, y0 is voltage, y1 is resistance
- admittance
-
x is voltage, y0 is current, y1 is admittance
- capacitance
-
x is voltage, y0 is charge, y1 is capacitance
- inductance
-
x is current, y0 is flux, y1 is inductance
- vccs
-
x is voltage, y0 is current, y1 is transconductance
In addition, all relevant parameters are available with the
appropriate prefix. See the section accessing data in code
blocks. Most are read-only.
The prefix d-> refers to the element being processed. This data
is read-write.
6.1.2 Model section
- base
- (optional)
The keyword BASE is used as a flag to say this is a base for
other models. When the base flag is set, others can be derived from
it and used interchangeably with the same device type.
- dev_type
- (required, all)
This is the name of the device type associated with this model type.
- level
- (optional, final only)
When several models are derived from a base, the numeric level is used
as a parameter to select which one to use.
- inherit
- (optional)
The model being defined inherits from the named base model. There is
no limit to the depth if inheritance.
- keys
- (required for base, optional otherwise)
This is a list of the keywords that are used to identify the model,
and assign attributes. See the section Keys subsection for
details.
- independent
- (optional)
This is a section describing parameters that are not dependent on size
or temperature. See the section Independent subsection for
details.
- size_dependent
- (optional)
This is a section describing parameters that are dependent on size.
See the section Size_dependent subsection for details.
- temperature_dependent
- (optional)
This is a section describing parameters that are dependent on
temperature. See the section Temperature_dependent subsection
for details.
- tr_eval
- (required once in hierarchy)
This is a section containing evaluation code for the whole device.
See the section Tr_eval subsection for details.
Keys subsection
The keys subsection consists of a number of keywords that are
used in the .model statement to identify this model. Different
keys can be used to represent variants, such as “NMOS” and
“PMOS” to represent the N and P channel devices. Each one is
followed by an assignment to be made when the key is present.
It is required, at least once in the hierarchy. Additional keys can
be used to select a particular model, as an alternative to the level parameter.
Independent subsection
The independent subsection list all of the “independent”
parameters supplied by the user in the .model statement.
Raw_parameters subsubsection
This subsubsection lists all of the “raw parameters”, the parameters
supplied by the user on the .model line. The format and
available attributes are described in the “Parameter lists” section,
which follows.
Calculated_parameters subsubsection
This subsubsection lists all of the “calculated parameters”, the
parameters not supplied by the user. Instead, they are calculated
based on other input. The format and available attributes are
described in the “Parameter lists” section, which follows.
Override subsubsection
This subsubsection lists parameters that have already been defined in
base classes, that need a change for this particular type. You can
override most attributes, giving the benefit of defining it locally,
while retaining most from the base. The format and available
attributes are described in the “Parameter lists” section, which
follows.
Code_pre and Code_post subsections
These subsubsections define C++ code that is inserted into the
function that calculates values, scales, and checks limits. The block
code_pre is inserted before the automatically generated code.
The block code_post is inserted after the automatically
generated code.
Size_dependent subsection
The size_dependent subsubsection is similar to the independent subsubsection except that it defines a base paramater and
scale factors so a custom value can be generated based on the device
size.
Every parameter in this subsubsection actually generates a set of
four. The first is the base, as in the independent
subsubsection. In addition, the same name prefixed by “L” is
the length dependency, the name prefixed by “W” is the width
dependency, and the name prefixed by “P” is the product
(length * width) dependency.
You must provide a code_pre section, which must declare and
define values for “L” (length) and “W” (width).
The actual value is calculated by: nom + ld/L + wd/W +
pd/(W*L);, where nom is the nominal value, ld is the
length dependency (key name has the “L” prefix), wd is
the width dependency (key name has the “W” prefix), and pd is the product dependency (key name has the “P” prefix).
Temperature_dependent subsection
The temperature_dependent subsubsection contains a list of
parameters that are calculated based on temperature, and two code
blocks (code_pre and code_post to make the calculations.
This code is evaluated at run time, possibly every time step, whenever
temperature changes. Some Spice models throw calculations not related
to temperature into the temperature block. This is very bad practice.
In Gnucap, temperature is local and time variant.
Tr_eval subsection
The tr_eval subsubsection is the actual model evaluation code
for nonlinear DC and transient analysis. This code must calculate all
state variables (data listed as “calculated” in the device section, except those that are part of one of the subcircuit
elements. Inputs and outputs are through the d-> structure.
This function only needs to fill in the calculated data. The
details, like differentiating charge in capacitors, is left to the
subcircuit elements. It is also not necessary to check convergence.
This, too, is left to the subcircuit elements.
6.1.3 Accessing data in code blocks
Most parameters are available, usually read-only, in any code block,
with the appropriate prefix:
- p->
-
The parent device, usually the device being defined by the .model file. This is usually the “calculated parameters” under
“device” in the .model file.
- c->
-
The “common” belonging to the parent device. This consists of all
of the parameters in the common section of the .model
file.
- m->
-
This is the “model” parameters, all of the parameters in the model section of the .model file, except those listed as “size
dependent”.
- b->
-
This is the sized value of the size dependent parameters in the model section. “B” is for “bin”, which is derived from the
concept of “binning” of models.
- d->
-
This is the device parameters. In evaluation functions, it is
read-write.
- t.
-
This is the device values, scaled by temperature.
6.1.4 Parameter lists
The format for each item is: type, name, comment, attributes, semicolon.
The available attributes are:
- name
-
This is the name to be used for input in the data file. It is also
the name this parameter is listed as when the internal data is
printed.
- alt_name
-
This is an alternate name used for input.
- default
-
This is the initial default value, set by the constructor.
- calculate
-
If no value is supplied, the program will calculate it using this
formula.
- quiet_min
-
If the input or calculated value is less than this number, substitute
this number without warning.
- quiet_max
-
If the input or calculated value is more than this number, substitute
this number without warning.
- final_default
-
This is the final default value, supplied after all attempts to fill
or calculate it fail.
- offset
-
Add this number to the input value to get the value actually stored in
memory. Example: double temperature “” offset=273;. This
sample allows data entry in degrees Celsius, but storage in Kelvin.
- scale
-
Multiply the input value by this number to get the value actually
stored in memory. Example: double length “” scale=1e6;.
This sample allows data entry in microns, but storage in meters.
- positive
-
This number is always positive. The magnitude of the entered value is
stored.
- octal
-
The number read is interpreted as octal (base 8), instead of the usual
base 10.
- print_test
-
This is a test to determine whether the value is printed in a standard
listing or not. The value is printed only if this test evaluates to
true at run time. If print_test is omitted, it is always
printed.
- calc_print_test
-
This is a test to determine whether the value is printed as a comment
in a standard listing or not. The value is printed only if this test
evaluates to true at run time. If calc_print_test is omitted,
it is never printed.