# Options and Options Management

`options.h` defines `SimulatorOptions`, the flat struct holding every simulator-wide option (device defaults, tolerances, Newton-Raphson and homotopy tuning, per-analysis-family knobs, output behavior). `ciroptions.cpp` implements the [`Circuit`](circuit.md) methods that let the rest of the simulator read and write these options while keeping track of which categories of change occurred, so [`elaborateChanges()`](cirparams.md) can redo only the work a given change actually requires.

## `SimulatorOptions`

A plain struct wrapped for parameter access by `IStruct<SimulatorOptions>` (see [Parameterized Objects](parameterized.md)); its `Introspection<SimulatorOptions>::setup()` specialization (in `options.cpp`) registers every field by name, which is what makes options settable through the `options` command and readable through `$temp`/`$scale`-style expressions via [`OptionsResolver`](circuit.md). Its default constructor sets every option to its documented default (each field has an inline comment giving its valid range and meaning). `operator==`/`operator!=` are defaulted (C++20 memberwise comparison), which `optionsDiffer()` and `Circuit::setOptions(IStruct<SimulatorOptions>&)` rely on to detect whether anything actually changed.

Fields fall into a few groups by name prefix:

- Core/device defaults and tolerances: `temp`, `tnom`, `gmin`, `gshunt`, `minr`, `scale`, `tolmode`, `tolscale`, `reltol`, `abstol`, `vntol`, `chgtol`, `fluxtol`, `relrefsol`/`relrefres`/`relreflte`/`relref`.
- Matrix/solution sanity checks: `matrixcheck`, `rhscheck`, `solutioncheck`, `rcondcheck`.
- Sweep behavior: `sweep_pointmarker`, `sweep_debug`.
- Newton-Raphson tuning shared by every analysis: `nr_debug`, `nr_bypass`, `nr_convtol`, `nr_bypasstol`, `nr_conviter`, `nr_residualcheck`, `nr_damping`, `nr_force`, `nr_nsforce`, `nr_contbypass`.
- Homotopy (gmin/source stepping) tuning: the `homotopy_*` fields.
- Per-analysis-family option blocks, each consumed by the corresponding analysis: `op_*` (operating point), `smsig_debug` (small-signal analyses), `tran_*` (transient), `hb_*` (harmonic balance), `pss_*` (periodic steady state).
- Output/strictness behavior: `rawfile`, `strictoutput`, `strictsave`, `strictforce`, `accounting`.

`tolmode`/`relrefsol`/`relrefres`/`relreflte`/`relref`/`rawfile` are enumerated `Id`-valued options; their legal values are exposed as static `Id` members (`tolmodeSpice`/`tolmodeVa`/`tolmodeMixed`, `relrefPointLocal`/`relrefLocal`/`relrefPointGlobal`/`relrefGlobal`/`relrefRelref`, `relrefAlllocal`/`relrefSigglobal`/`relrefAllglobal`, `rawfileAscii`/`rawfileBinary`). `debugMode()` is true if any of the per-subsystem `*_debug` flags is set.

## Change-impact classification

Because changing an option can be expensive to react to (it may require rebuilding node collapsing, re-propagating the whole parameter hierarchy, or rebuilding tolerance tables), `SimulatorOptions` classifies its own fields into four independent, possibly-overlapping categories, each a static `unordered_map<Id, ParameterIndex>` populated once by `staticInitialize()` (invoked via a static initializer):

| Category | Member map | Options currently in it | Effect when changed |
|---|---|---|---|
| Mapping-affecting | `mappingAffectingOptions` | `tnom`, `temp`, `gmin`, `gdev`, `minr`, `scale`, `reltol`, `vntol`, `abstol`, `chgtol`, `fluxtol` | Forces a full `Circuit::setup()` (node collapsing may depend on these, since they are exposed through the OSDI interface to device code). |
| Parametrization-affecting | `parametrizationAffectingOptions` | `temp`, `scale` | Forces full parameter propagation across the whole hierarchy (these are the two options exposed as `$temp`/`$scale` in parameter expressions). |
| Hierarchy-affecting | `hierarchyAffectingOptions` | none currently | Would force a hierarchy-change check on every instance, not just ones with changed parameters. |
| Tolerances-affecting | `tolerancesAffectingOptions` | `tolmode`, `abstol`, `chgtol`, `vntol`, `fluxtol` | Forces `Circuit::setStaticTolerances()` and `CommonData::enumerateNatures()` to rerun. |

`optionsDiffer(list, other)` checks whether any option named in a given category map differs between `this` and `other`, using `Introspection<SimulatorOptions>::memberEqual()` for a per-field comparison.

## `Circuit`'s option API

- **`setOption(name, value, s)`**: looks the option up by name via the wrapping `IStruct<SimulatorOptions>`, sets it, and - if the value actually changed - sets the corresponding `Circuit` flags (`HierarchyAffectingOptionsChanged`, `ParametrizationAffectingOptionsChanged`, `MappingAffectingOptionsChanged`, `TolerancesAffectingOptionsChanged`, see [Circuit](circuit.md)) by checking membership in each of the four category maps above.
- **`setOptions(IStruct<SimulatorOptions>& opt)`**: replaces the whole options struct at once (used when applying a caller-supplied options snapshot), diffing against each category map before overwriting so the right flags are set even though individual `setOption()` calls never happened.
- **`setOptions(const PTParameters& params, s)`**: applies a parsed `options` netlist/command block - constant-valued options directly, expression-valued ones evaluated through `variableEvaluator()` first - calling `setOption()` for each so per-option change tracking still applies. This is done manually (not through the generic `Parameterized::setParameters()` used elsewhere) precisely so each option's category membership can be intercepted.
- **`clearOptions(s)`**: resets to a default-constructed `IStruct<SimulatorOptions>` via `setOptions()`.

All four feed into [`Circuit::elaborateChanges()`](cirparams.md), which reads back the four `*OptionsChanged` flags to decide which parts of the elaboration pipeline actually need to rerun.

## `OptionsResolver`

`OptionsResolver` (declared in `circuit.h`) is a `Resolver` (see [Context](context.md)) installed on the parameter evaluator's context stack so netlist parameter expressions can reference `$temp` and `$scale`. Its constructor builds a small map from the special `$`-prefixed name to a `(value-slot, ParameterIndex)` pair, restricted to whichever of `temp`/`scale` are present in `parametrizationAffectingOptions`; `get(name)` looks the name up, pulls the current value out of the wrapped `IStruct<SimulatorOptions>` via `getParameter()`, and returns a pointer to a cached `Value`.
