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

  2. The port list “ports”, which is a list of the nodes interfacing to the outside.

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


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

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