Using the model compiler

## 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 `model`s 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:
   - 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.